Skip to content

Commit 746fd16

Browse files
author
Jorge Aparicio
committed
---
yaml --- r: 167486 b: refs/heads/snap-stage3 c: ea94a90 h: refs/heads/master v: v3
1 parent 5a9261a commit 746fd16

25 files changed

+446
-899
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: 023dfb0c898d851dee6ace2f8339b73b5287136b
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 7d4f4876d65bddf101784230c0347adcb01e5c21
4+
refs/heads/snap-stage3: ea94a90488e6b4701581079339de3595389e5b15
55
refs/heads/try: 5204084bd2e46af7cc6e0147430e44dd0d657bbb
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d

branches/snap-stage3/src/librustc/metadata/encoder.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
14021402
}
14031403
ty::TypeTraitItem(associated_type) => {
14041404
encode_name(rbml_w, associated_type.name);
1405-
encode_def_id(rbml_w, associated_type.def_id);
14061405

14071406
let elem = ast_map::PathName(associated_type.name);
14081407
encode_path(rbml_w,

branches/snap-stage3/src/librustc/middle/traits/error_reporting.rs

Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,13 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
7777
"overflow evaluating the requirement `{}`",
7878
predicate.user_string(infcx.tcx)).as_slice());
7979

80-
suggest_new_overflow_limit(infcx, obligation.cause.span);
80+
let current_limit = infcx.tcx.sess.recursion_limit.get();
81+
let suggested_limit = current_limit * 2;
82+
infcx.tcx.sess.span_note(
83+
obligation.cause.span,
84+
format!(
85+
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
86+
suggested_limit)[]);
8187

8288
note_obligation_cause(infcx, obligation);
8389
}
@@ -159,76 +165,73 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
159165
// ambiguous impls. The latter *ought* to be a
160166
// coherence violation, so we don't report it here.
161167

162-
let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
168+
let trait_ref = match obligation.predicate {
169+
ty::Predicate::Trait(ref trait_predicate) => {
170+
infcx.resolve_type_vars_if_possible(
171+
&trait_predicate.to_poly_trait_ref())
172+
}
173+
_ => {
174+
infcx.tcx.sess.span_bug(
175+
obligation.cause.span,
176+
format!("ambiguity from something other than a trait: {}",
177+
obligation.predicate.repr(infcx.tcx)).as_slice());
178+
}
179+
};
163180

164-
debug!("maybe_report_ambiguity(predicate={}, obligation={})",
165-
predicate.repr(infcx.tcx),
166-
obligation.repr(infcx.tcx));
181+
let self_ty = trait_ref.self_ty();
167182

168-
match predicate {
169-
ty::Predicate::Trait(ref data) => {
170-
let trait_ref = data.to_poly_trait_ref();
171-
let self_ty = trait_ref.self_ty();
172-
let all_types = &trait_ref.substs().types;
173-
if all_types.iter().any(|&t| ty::type_is_error(t)) {
174-
} else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
175-
// This is kind of a hack: it frequently happens that some earlier
176-
// error prevents types from being fully inferred, and then we get
177-
// a bunch of uninteresting errors saying something like "<generic
178-
// #0> doesn't implement Sized". It may even be true that we
179-
// could just skip over all checks where the self-ty is an
180-
// inference variable, but I was afraid that there might be an
181-
// inference variable created, registered as an obligation, and
182-
// then never forced by writeback, and hence by skipping here we'd
183-
// be ignoring the fact that we don't KNOW the type works
184-
// out. Though even that would probably be harmless, given that
185-
// we're only talking about builtin traits, which are known to be
186-
// inhabited. But in any case I just threw in this check for
187-
// has_errors() to be sure that compilation isn't happening
188-
// anyway. In that case, why inundate the user.
189-
if !infcx.tcx.sess.has_errors() {
190-
if
191-
infcx.tcx.lang_items.sized_trait()
192-
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
193-
{
194-
infcx.tcx.sess.span_err(
195-
obligation.cause.span,
196-
format!(
197-
"unable to infer enough type information about `{}`; \
198-
type annotations required",
199-
self_ty.user_string(infcx.tcx)).as_slice());
200-
} else {
201-
infcx.tcx.sess.span_err(
202-
obligation.cause.span,
203-
format!(
204-
"type annotations required: cannot resolve `{}`",
205-
predicate.user_string(infcx.tcx)).as_slice());
206-
note_obligation_cause(infcx, obligation);
207-
}
208-
}
209-
} else if !infcx.tcx.sess.has_errors() {
210-
// Ambiguity. Coherence should have reported an error.
211-
infcx.tcx.sess.span_bug(
183+
debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
184+
trait_ref.repr(infcx.tcx),
185+
self_ty.repr(infcx.tcx),
186+
obligation.repr(infcx.tcx));
187+
let all_types = &trait_ref.substs().types;
188+
if all_types.iter().any(|&t| ty::type_is_error(t)) {
189+
} else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
190+
// This is kind of a hack: it frequently happens that some earlier
191+
// error prevents types from being fully inferred, and then we get
192+
// a bunch of uninteresting errors saying something like "<generic
193+
// #0> doesn't implement Sized". It may even be true that we
194+
// could just skip over all checks where the self-ty is an
195+
// inference variable, but I was afraid that there might be an
196+
// inference variable created, registered as an obligation, and
197+
// then never forced by writeback, and hence by skipping here we'd
198+
// be ignoring the fact that we don't KNOW the type works
199+
// out. Though even that would probably be harmless, given that
200+
// we're only talking about builtin traits, which are known to be
201+
// inhabited. But in any case I just threw in this check for
202+
// has_errors() to be sure that compilation isn't happening
203+
// anyway. In that case, why inundate the user.
204+
if !infcx.tcx.sess.has_errors() {
205+
if infcx.tcx.lang_items.sized_trait()
206+
.map_or(false, |sized_id| sized_id == trait_ref.def_id()) {
207+
infcx.tcx.sess.span_err(
212208
obligation.cause.span,
213209
format!(
214-
"coherence failed to report ambiguity: \
215-
cannot locate the impl of the trait `{}` for \
216-
the type `{}`",
217-
trait_ref.user_string(infcx.tcx),
210+
"unable to infer enough type information about `{}`; type annotations \
211+
required",
218212
self_ty.user_string(infcx.tcx)).as_slice());
219-
}
220-
}
221-
222-
_ => {
223-
if !infcx.tcx.sess.has_errors() {
213+
} else {
224214
infcx.tcx.sess.span_err(
225215
obligation.cause.span,
226216
format!(
227-
"type annotations required: cannot resolve `{}`",
228-
predicate.user_string(infcx.tcx)).as_slice());
217+
"unable to infer enough type information to \
218+
locate the impl of the trait `{}` for \
219+
the type `{}`; type annotations required",
220+
trait_ref.user_string(infcx.tcx),
221+
self_ty.user_string(infcx.tcx)).as_slice());
229222
note_obligation_cause(infcx, obligation);
230223
}
231224
}
225+
} else if !infcx.tcx.sess.has_errors() {
226+
// Ambiguity. Coherence should have reported an error.
227+
infcx.tcx.sess.span_bug(
228+
obligation.cause.span,
229+
format!(
230+
"coherence failed to report ambiguity: \
231+
cannot locate the impl of the trait `{}` for \
232+
the type `{}`",
233+
trait_ref.user_string(infcx.tcx),
234+
self_ty.user_string(infcx.tcx)).as_slice());
232235
}
233236
}
234237

@@ -332,12 +335,3 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
332335
}
333336
}
334337

335-
pub fn suggest_new_overflow_limit(infcx: &InferCtxt, span: Span) {
336-
let current_limit = infcx.tcx.sess.recursion_limit.get();
337-
let suggested_limit = current_limit * 2;
338-
infcx.tcx.sess.span_note(
339-
span,
340-
format!(
341-
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
342-
suggested_limit)[]);
343-
}

branches/snap-stage3/src/librustc/middle/traits/fulfill.rs

Lines changed: 109 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use middle::infer::{InferCtxt};
11+
use middle::infer::{mod, InferCtxt};
1212
use middle::mem_categorization::Typer;
13-
use middle::ty::{mod, RegionEscape, Ty};
13+
use middle::ty::{mod, AsPredicate, RegionEscape, Ty, ToPolyTraitRef};
1414
use std::collections::HashSet;
1515
use std::collections::hash_map::Entry::{Occupied, Vacant};
1616
use std::default::Default;
@@ -23,6 +23,7 @@ use super::CodeAmbiguity;
2323
use super::CodeProjectionError;
2424
use super::CodeSelectionError;
2525
use super::FulfillmentError;
26+
use super::Obligation;
2627
use super::ObligationCause;
2728
use super::PredicateObligation;
2829
use super::project;
@@ -109,8 +110,6 @@ impl<'tcx> FulfillmentContext<'tcx> {
109110
/// `projection_ty` again.
110111
pub fn normalize_projection_type<'a>(&mut self,
111112
infcx: &InferCtxt<'a,'tcx>,
112-
param_env: &ty::ParameterEnvironment<'tcx>,
113-
typer: &Typer<'tcx>,
114113
projection_ty: ty::ProjectionTy<'tcx>,
115114
cause: ObligationCause<'tcx>)
116115
-> Ty<'tcx>
@@ -122,16 +121,18 @@ impl<'tcx> FulfillmentContext<'tcx> {
122121

123122
// FIXME(#20304) -- cache
124123

125-
let mut selcx = SelectionContext::new(infcx, param_env, typer);
126-
let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0);
127-
128-
for obligation in normalized.obligations.into_iter() {
129-
self.register_predicate_obligation(infcx, obligation);
130-
}
124+
let ty_var = infcx.next_ty_var();
125+
let projection =
126+
ty::Binder(ty::ProjectionPredicate {
127+
projection_ty: projection_ty,
128+
ty: ty_var
129+
});
130+
let obligation = Obligation::new(cause, projection.as_predicate());
131+
self.register_predicate(infcx, obligation);
131132

132-
debug!("normalize_associated_type: result={}", normalized.value.repr(infcx.tcx));
133+
debug!("normalize_associated_type: result={}", ty_var.repr(infcx.tcx));
133134

134-
normalized.value
135+
ty_var
135136
}
136137

137138
pub fn register_builtin_bound<'a>(&mut self,
@@ -142,7 +143,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
142143
{
143144
match predicate_for_builtin_bound(infcx.tcx, cause, builtin_bound, 0, ty) {
144145
Ok(predicate) => {
145-
self.register_predicate_obligation(infcx, predicate);
146+
self.register_predicate(infcx, predicate);
146147
}
147148
Err(ErrorReported) => { }
148149
}
@@ -157,14 +158,10 @@ impl<'tcx> FulfillmentContext<'tcx> {
157158
register_region_obligation(infcx.tcx, t_a, r_b, cause, &mut self.region_obligations);
158159
}
159160

160-
pub fn register_predicate_obligation<'a>(&mut self,
161-
infcx: &InferCtxt<'a,'tcx>,
162-
obligation: PredicateObligation<'tcx>)
161+
pub fn register_predicate<'a>(&mut self,
162+
infcx: &InferCtxt<'a,'tcx>,
163+
obligation: PredicateObligation<'tcx>)
163164
{
164-
// this helps to reduce duplicate errors, as well as making
165-
// debug output much nicer to read and so on.
166-
let obligation = infcx.resolve_type_vars_if_possible(&obligation);
167-
168165
if !self.duplicate_set.insert(obligation.predicate.clone()) {
169166
debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx));
170167
return;
@@ -293,7 +290,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
293290
// Now go through all the successful ones,
294291
// registering any nested obligations for the future.
295292
for new_obligation in new_obligations.into_iter() {
296-
self.register_predicate_obligation(selcx.infcx(), new_obligation);
293+
self.register_predicate(selcx.infcx(), new_obligation);
297294
}
298295
}
299296

@@ -401,18 +398,104 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
401398
project_obligation.repr(tcx),
402399
result.repr(tcx));
403400
match result {
404-
Ok(Some(obligations)) => {
405-
new_obligations.extend(obligations.into_iter());
401+
Ok(()) => {
406402
true
407403
}
408-
Ok(None) => {
404+
Err(project::ProjectionError::TooManyCandidates) => {
405+
// Without more type information, we can't say much.
409406
false
410407
}
411-
Err(err) => {
408+
Err(project::ProjectionError::NoCandidate) => {
409+
// This means that we have a type like `<T as
410+
// Trait>::name = U` but we couldn't find any more
411+
// information. This could just be that we're in a
412+
// function like:
413+
//
414+
// fn foo<T:Trait>(...)
415+
//
416+
// in which case this is not an error. But it
417+
// might also mean we're in a situation where we
418+
// don't actually know that `T : Trait` holds,
419+
// which would be weird (e.g., if `T` was not a
420+
// parameter type but a normal type, like `int`).
421+
//
422+
// So what we do is to (1) add a requirement that
423+
// `T : Trait` (just in case) and (2) try to unify
424+
// `U` with `<T as Trait>::name`.
425+
426+
if !ty::binds_late_bound_regions(selcx.tcx(), data) {
427+
// Check that `T : Trait` holds.
428+
let trait_ref = data.to_poly_trait_ref();
429+
new_obligations.push(obligation.with(trait_ref.as_predicate()));
430+
431+
// Fallback to `<T as Trait>::name`. If this
432+
// fails, then the output must be at least
433+
// somewhat constrained, and we cannot verify
434+
// that constraint, so yield an error.
435+
let ty_projection = ty::mk_projection(tcx,
436+
trait_ref.0.clone(),
437+
data.0.projection_ty.item_name);
438+
439+
debug!("process_predicate: falling back to projection {}",
440+
ty_projection.repr(selcx.tcx()));
441+
442+
match infer::mk_eqty(selcx.infcx(),
443+
true,
444+
infer::EquatePredicate(obligation.cause.span),
445+
ty_projection,
446+
data.0.ty) {
447+
Ok(()) => { }
448+
Err(_) => {
449+
debug!("process_predicate: fallback failed to unify; error");
450+
errors.push(
451+
FulfillmentError::new(
452+
obligation.clone(),
453+
CodeSelectionError(Unimplemented)));
454+
}
455+
}
456+
457+
true
458+
} else {
459+
// If we have something like
460+
//
461+
// for<'a> <T<'a> as Trait>::name == &'a int
462+
//
463+
// there is no "canonical form" for us to
464+
// make, so just report the lack of candidates
465+
// as an error.
466+
467+
debug!("process_predicate: can't fallback, higher-ranked");
468+
errors.push(
469+
FulfillmentError::new(
470+
obligation.clone(),
471+
CodeSelectionError(Unimplemented)));
472+
473+
true
474+
}
475+
}
476+
Err(project::ProjectionError::MismatchedTypes(e)) => {
412477
errors.push(
413478
FulfillmentError::new(
414479
obligation.clone(),
415-
CodeProjectionError(err)));
480+
CodeProjectionError(e)));
481+
true
482+
}
483+
Err(project::ProjectionError::TraitSelectionError(_)) => {
484+
// There was an error matching `T : Trait` (which
485+
// is a pre-requisite for `<T as Trait>::Name`
486+
// being valid). We could just report the error
487+
// now, but that tends to lead to double error
488+
// reports for the user (one for the obligation `T
489+
// : Trait`, typically incurred somewhere else,
490+
// and one from here). Instead, we'll create the
491+
// `T : Trait` obligation and add THAT as a
492+
// requirement. This will (eventually) trigger the
493+
// same error, but it will also wind up flagged as
494+
// a duplicate if another requirement that `T :
495+
// Trait` arises from somewhere else.
496+
let trait_predicate = data.to_poly_trait_ref();
497+
let trait_obligation = obligation.with(trait_predicate.as_predicate());
498+
new_obligations.push(trait_obligation);
416499
true
417500
}
418501
}

0 commit comments

Comments
 (0)