Skip to content

Commit 1cf2ca5

Browse files
committed
---
yaml --- r: 277374 b: refs/heads/try c: b50a2ff h: refs/heads/master
1 parent 9ae6a39 commit 1cf2ca5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+570
-182
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 6dbb0e86aec11050480beb76eade6fb805010ba7
33
refs/heads/snap-stage3: 235d77457d80b549dad3ac36d94f235208a1eafb
4-
refs/heads/try: bb9ec8256372e6bc6187fa977bd203e2fb09e082
4+
refs/heads/try: b50a2ff4d15324bebf6ce8a1661448195c213f5d
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/src/doc/book/const-and-static.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ the result of a function call or anything similarly complex or at runtime.
7979

8080
Almost always, if you can choose between the two, choose `const`. It’s pretty
8181
rare that you actually want a memory location associated with your constant,
82-
and using a const allows for optimizations like constant propagation not only
82+
and using a `const` allows for optimizations like constant propagation not only
8383
in your crate but downstream crates.

branches/try/src/librustc/infer/mod.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use ty::fold::TypeFoldable;
3535
use ty::relate::{Relate, RelateResult, TypeRelation};
3636
use traits::{self, PredicateObligations, ProjectionMode};
3737
use rustc_data_structures::unify::{self, UnificationTable};
38-
use std::cell::{RefCell, Ref};
38+
use std::cell::{Cell, RefCell, Ref};
3939
use std::fmt;
4040
use syntax::ast;
4141
use syntax::codemap;
@@ -110,6 +110,25 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
110110
// documentation for `ProjectionMode`.
111111
projection_mode: ProjectionMode,
112112

113+
// When an error occurs, we want to avoid reporting "derived"
114+
// errors that are due to this original failure. Normally, we
115+
// handle this with the `err_count_on_creation` count, which
116+
// basically just tracks how many errors were reported when we
117+
// started type-checking a fn and checks to see if any new errors
118+
// have been reported since then. Not great, but it works.
119+
//
120+
// However, when errors originated in other passes -- notably
121+
// resolve -- this heuristic breaks down. Therefore, we have this
122+
// auxiliary flag that one can set whenever one creates a
123+
// type-error that is due to an error in a prior pass.
124+
//
125+
// Don't read this flag directly, call `is_tainted_by_errors()`
126+
// and `set_tainted_by_errors()`.
127+
tainted_by_errors_flag: Cell<bool>,
128+
129+
// Track how many errors were reported when this infcx is created.
130+
// If the number of errors increases, that's also a sign (line
131+
// `tained_by_errors`) to avoid reporting certain kinds of errors.
113132
err_count_on_creation: usize,
114133
}
115134

@@ -379,6 +398,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>,
379398
reported_trait_errors: RefCell::new(FnvHashSet()),
380399
normalize: false,
381400
projection_mode: projection_mode,
401+
tainted_by_errors_flag: Cell::new(false),
382402
err_count_on_creation: tcx.sess.err_count()
383403
}
384404
}
@@ -1128,15 +1148,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11281148
.map(|method| resolve_ty(method.ty)))
11291149
}
11301150

1131-
pub fn errors_since_creation(&self) -> bool {
1132-
self.tcx.sess.err_count() - self.err_count_on_creation != 0
1151+
/// True if errors have been reported since this infcx was
1152+
/// created. This is sometimes used as a heuristic to skip
1153+
/// reporting errors that often occur as a result of earlier
1154+
/// errors, but where it's hard to be 100% sure (e.g., unresolved
1155+
/// inference variables, regionck errors).
1156+
pub fn is_tainted_by_errors(&self) -> bool {
1157+
debug!("is_tainted_by_errors(err_count={}, err_count_on_creation={}, \
1158+
tainted_by_errors_flag={})",
1159+
self.tcx.sess.err_count(),
1160+
self.err_count_on_creation,
1161+
self.tainted_by_errors_flag.get());
1162+
1163+
if self.tcx.sess.err_count() > self.err_count_on_creation {
1164+
return true; // errors reported since this infcx was made
1165+
}
1166+
self.tainted_by_errors_flag.get()
1167+
}
1168+
1169+
/// Set the "tainted by errors" flag to true. We call this when we
1170+
/// observe an error from a prior pass.
1171+
pub fn set_tainted_by_errors(&self) {
1172+
debug!("set_tainted_by_errors()");
1173+
self.tainted_by_errors_flag.set(true)
11331174
}
11341175

11351176
pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
11361177
match self.tables.borrow().node_types.get(&id) {
11371178
Some(&t) => t,
11381179
// FIXME
1139-
None if self.errors_since_creation() =>
1180+
None if self.is_tainted_by_errors() =>
11401181
self.tcx.types.err,
11411182
None => {
11421183
bug!("no type for node {}: {} in fcx",
@@ -1158,7 +1199,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11581199
free_regions: &FreeRegionMap,
11591200
subject_node_id: ast::NodeId) {
11601201
let errors = self.region_vars.resolve_regions(free_regions, subject_node_id);
1161-
if !self.errors_since_creation() {
1202+
if !self.is_tainted_by_errors() {
11621203
// As a heuristic, just skip reporting region errors
11631204
// altogether if other errors have been reported while
11641205
// this infcx was in use. This is totally hokey but

branches/try/src/librustc/infer/sub.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
9191
}
9292

9393
(&ty::TyError, _) | (_, &ty::TyError) => {
94+
infcx.set_tainted_by_errors();
9495
Ok(self.tcx().types.err)
9596
}
9697

branches/try/src/librustc/traits/error_reporting.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,12 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
624624
predicate,
625625
obligation);
626626

627+
// Ambiguity errors are often caused as fallout from earlier
628+
// errors. So just ignore them if this infcx is tainted.
629+
if infcx.is_tainted_by_errors() {
630+
return;
631+
}
632+
627633
match predicate {
628634
ty::Predicate::Trait(ref data) => {
629635
let trait_ref = data.to_poly_trait_ref();

branches/try/src/librustc_back/target/apple_base.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ pub fn opts() -> TargetOptions {
3333
}).unwrap_or((10, 7));
3434

3535
TargetOptions {
36-
// OSX has -dead_strip, which doesn't rely on ffunction_sections
36+
// OSX has -dead_strip, which doesn't rely on function_sections
3737
function_sections: false,
38-
linker: "cc".to_string(),
3938
dynamic_linking: true,
4039
executables: true,
4140
is_like_osx: true,

branches/try/src/librustc_back/target/arm_linux_androideabi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use target::Target;
1212

1313
pub fn target() -> Target {
1414
let mut base = super::android_base::opts();
15-
base.features = "+v7".to_string();
15+
base.features = "+v7,+vfp3,+d16".to_string();
1616

1717
Target {
1818
llvm_target: "arm-linux-androideabi".to_string(),

branches/try/src/librustc_back/target/bitrig_base.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
1515
TargetOptions {
16-
linker: "cc".to_string(),
1716
dynamic_linking: true,
1817
executables: true,
1918
linker_is_gnu: true,

branches/try/src/librustc_back/target/dragonfly_base.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
1515
TargetOptions {
16-
linker: "cc".to_string(),
1716
dynamic_linking: true,
1817
executables: true,
1918
linker_is_gnu: true,

branches/try/src/librustc_back/target/freebsd_base.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
1515
TargetOptions {
16-
linker: "cc".to_string(),
1716
dynamic_linking: true,
1817
executables: true,
1918
linker_is_gnu: true,

branches/try/src/librustc_back/target/netbsd_base.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
1515
TargetOptions {
16-
linker: "cc".to_string(),
1716
dynamic_linking: true,
1817
executables: true,
1918
linker_is_gnu: true,

branches/try/src/librustc_back/target/openbsd_base.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
1515
TargetOptions {
16-
linker: "cc".to_string(),
1716
dynamic_linking: true,
1817
executables: true,
1918
linker_is_gnu: true,

branches/try/src/librustc_back/target/solaris_base.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
1515
TargetOptions {
16-
linker: "cc".to_string(),
1716
dynamic_linking: true,
1817
executables: true,
1918
has_rpath: true,

branches/try/src/librustc_typeck/astconv.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ pub trait AstConv<'tcx> {
155155
_trait_ref: ty::TraitRef<'tcx>,
156156
_item_name: ast::Name)
157157
-> Ty<'tcx>;
158+
159+
/// Invoked when we encounter an error from some prior pass
160+
/// (e.g. resolve) that is translated into a ty-error. This is
161+
/// used to help suppress derived errors typeck might otherwise
162+
/// report.
163+
fn set_tainted_by_errors(&self);
158164
}
159165

160166
pub fn ast_region_to_region(tcx: &TyCtxt, lifetime: &hir::Lifetime)
@@ -1533,6 +1539,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
15331539
prim_ty_to_ty(tcx, base_segments, prim_ty)
15341540
}
15351541
Def::Err => {
1542+
this.set_tainted_by_errors();
15361543
return this.tcx().types.err;
15371544
}
15381545
_ => {

branches/try/src/librustc_typeck/check/_match.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
209209
let self_ty = fcx.to_ty(&qself.ty);
210210
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
211211
if d.base_def == Def::Err {
212+
fcx.infcx().set_tainted_by_errors();
212213
fcx.write_error(pat.id);
213214
return;
214215
}
@@ -628,6 +629,7 @@ fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
628629
let path_res = match tcx.def_map.borrow().get(&pat.id) {
629630
Some(&path_res) if path_res.base_def != Def::Err => path_res,
630631
_ => {
632+
fcx.infcx().set_tainted_by_errors();
631633
fcx.write_error(pat.id);
632634

633635
if let Some(subpats) = subpats {

branches/try/src/librustc_typeck/check/cast.rs

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,21 @@ use super::structurally_resolved_type;
4545

4646
use lint;
4747
use hir::def_id::DefId;
48+
use rustc::hir;
49+
use rustc::traits;
4850
use rustc::ty::{self, Ty, TypeFoldable};
4951
use rustc::ty::cast::{CastKind, CastTy};
50-
use syntax::codemap::Span;
51-
use rustc::hir;
5252
use syntax::ast;
53-
53+
use syntax::codemap::Span;
54+
use util::common::ErrorReported;
5455

5556
/// Reifies a cast check to be checked once we have full type information for
5657
/// a function context.
5758
pub struct CastCheck<'tcx> {
5859
expr: &'tcx hir::Expr,
5960
expr_ty: Ty<'tcx>,
6061
cast_ty: Ty<'tcx>,
62+
cast_span: Span,
6163
span: Span,
6264
}
6365

@@ -111,17 +113,37 @@ enum CastError {
111113
}
112114

113115
impl<'tcx> CastCheck<'tcx> {
114-
pub fn new(expr: &'tcx hir::Expr, expr_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, span: Span)
115-
-> CastCheck<'tcx> {
116-
CastCheck {
116+
pub fn new<'a>(fcx: &FnCtxt<'a, 'tcx>,
117+
expr: &'tcx hir::Expr,
118+
expr_ty: Ty<'tcx>,
119+
cast_ty: Ty<'tcx>,
120+
cast_span: Span,
121+
span: Span)
122+
-> Result<CastCheck<'tcx>, ErrorReported> {
123+
let check = CastCheck {
117124
expr: expr,
118125
expr_ty: expr_ty,
119126
cast_ty: cast_ty,
127+
cast_span: cast_span,
120128
span: span,
129+
};
130+
131+
// For better error messages, check for some obviously unsized
132+
// cases now. We do a more thorough check at the end, once
133+
// inference is more completely known.
134+
match cast_ty.sty {
135+
ty::TyTrait(..) | ty::TySlice(..) => {
136+
check.report_cast_to_unsized_type(fcx);
137+
Err(ErrorReported)
138+
}
139+
_ => {
140+
Ok(check)
141+
}
121142
}
122143
}
123144

124-
fn report_cast_error<'a>(&self, fcx: &FnCtxt<'a, 'tcx>,
145+
fn report_cast_error<'a>(&self,
146+
fcx: &FnCtxt<'a, 'tcx>,
125147
e: CastError) {
126148
match e {
127149
CastError::NeedViaPtr |
@@ -186,6 +208,61 @@ impl<'tcx> CastCheck<'tcx> {
186208
}
187209
}
188210

211+
fn report_cast_to_unsized_type<'a>(&self,
212+
fcx: &FnCtxt<'a, 'tcx>) {
213+
if
214+
self.cast_ty.references_error() ||
215+
self.expr_ty.references_error()
216+
{
217+
return;
218+
}
219+
220+
let tstr = fcx.infcx().ty_to_string(self.cast_ty);
221+
let mut err = fcx.type_error_struct(self.span, |actual| {
222+
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
223+
}, self.expr_ty, None);
224+
match self.expr_ty.sty {
225+
ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
226+
let mtstr = match mt {
227+
hir::MutMutable => "mut ",
228+
hir::MutImmutable => ""
229+
};
230+
if self.cast_ty.is_trait() {
231+
match fcx.tcx().sess.codemap().span_to_snippet(self.cast_span) {
232+
Ok(s) => {
233+
err.span_suggestion(self.cast_span,
234+
"try casting to a reference instead:",
235+
format!("&{}{}", mtstr, s));
236+
},
237+
Err(_) =>
238+
span_help!(err, self.cast_span,
239+
"did you mean `&{}{}`?", mtstr, tstr),
240+
}
241+
} else {
242+
span_help!(err, self.span,
243+
"consider using an implicit coercion to `&{}{}` instead",
244+
mtstr, tstr);
245+
}
246+
}
247+
ty::TyBox(..) => {
248+
match fcx.tcx().sess.codemap().span_to_snippet(self.cast_span) {
249+
Ok(s) => {
250+
err.span_suggestion(self.cast_span,
251+
"try casting to a `Box` instead:",
252+
format!("Box<{}>", s));
253+
},
254+
Err(_) =>
255+
span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
256+
}
257+
}
258+
_ => {
259+
span_help!(err, self.expr.span,
260+
"consider using a box or reference as appropriate");
261+
}
262+
}
263+
err.emit();
264+
}
265+
189266
fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
190267
let t_cast = self.cast_ty;
191268
let t_expr = self.expr_ty;
@@ -218,7 +295,9 @@ impl<'tcx> CastCheck<'tcx> {
218295
debug!("check_cast({}, {:?} as {:?})", self.expr.id, self.expr_ty,
219296
self.cast_ty);
220297

221-
if self.expr_ty.references_error() || self.cast_ty.references_error() {
298+
if !fcx.type_is_known_to_be_sized(self.cast_ty, self.span) {
299+
self.report_cast_to_unsized_type(fcx);
300+
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {
222301
// No sense in giving duplicate error messages
223302
} else if self.try_coercion_cast(fcx) {
224303
self.trivial_cast_lint(fcx);
@@ -403,3 +482,17 @@ impl<'tcx> CastCheck<'tcx> {
403482
}
404483

405484
}
485+
486+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
487+
fn type_is_known_to_be_sized(&self,
488+
ty: Ty<'tcx>,
489+
span: Span)
490+
-> bool
491+
{
492+
traits::type_known_to_meet_builtin_bound(self.infcx(),
493+
ty,
494+
ty::BoundSized,
495+
span)
496+
}
497+
}
498+

0 commit comments

Comments
 (0)