Skip to content

Commit 29181b3

Browse files
authored
Auto merge of #37717 - nikomatsakis:region-obligations-pre, r=eddyb
Refactoring towards region obligation Two refactorings towards the intermediate goal of propagating region obligations through the `InferOk` structure (which in turn leads to the possibility of lazy normalization). 1. Remove `TypeOrigin` and add `ObligationCause` - as we converge subtyping and obligations and so forth, the ability to keep these types distinct gets harder 2. Propagate obligations from `InferOk` into the surrounding fulfillment context After these land, I have a separate branch (which still needs a bit of work) that can make the actual change to stop directly adding subregion edges and instead propagate obligations. (This should also make it easier to fix the unsoundness in specialization around lifetimes.) r? @eddyb
2 parents 6cd5be8 + 48dc6e2 commit 29181b3

28 files changed

+470
-465
lines changed

src/librustc/infer/combine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
274274
{
275275
let mut generalize = Generalizer {
276276
infcx: self.infcx,
277-
span: self.trace.origin.span(),
277+
span: self.trace.cause.span,
278278
for_vid: for_vid,
279279
make_region_vars: make_region_vars,
280280
cycle_detected: false

src/librustc/infer/error_reporting.rs

+59-16
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ use hir::print as pprust;
8080
use lint;
8181
use hir::def::Def;
8282
use hir::def_id::DefId;
83-
use infer::{self, TypeOrigin};
83+
use infer;
8484
use middle::region;
85+
use traits::{ObligationCause, ObligationCauseCode};
8586
use ty::{self, TyCtxt, TypeFoldable};
8687
use ty::{Region, ReFree};
8788
use ty::error::TypeError;
@@ -524,10 +525,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
524525

525526
fn note_error_origin(&self,
526527
err: &mut DiagnosticBuilder<'tcx>,
527-
origin: &TypeOrigin)
528+
cause: &ObligationCause<'tcx>)
528529
{
529-
match origin {
530-
&TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
530+
match cause.code {
531+
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
531532
hir::MatchSource::IfLetDesugar {..} => {
532533
err.span_note(arm_span, "`if let` arm with an incompatible type");
533534
}
@@ -541,7 +542,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
541542

542543
pub fn note_type_err(&self,
543544
diag: &mut DiagnosticBuilder<'tcx>,
544-
origin: TypeOrigin,
545+
cause: &ObligationCause<'tcx>,
545546
secondary_span: Option<(Span, String)>,
546547
values: Option<ValuePairs<'tcx>>,
547548
terr: &TypeError<'tcx>)
@@ -558,7 +559,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
558559
}
559560
};
560561

561-
let span = origin.span();
562+
let span = cause.span;
562563

563564
if let Some((expected, found)) = expected_found {
564565
let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
@@ -588,7 +589,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
588589
diag.span_label(sp, &msg);
589590
}
590591

591-
self.note_error_origin(diag, &origin);
592+
self.note_error_origin(diag, &cause);
592593
self.check_and_note_conflicting_crates(diag, terr, span);
593594
self.tcx.note_and_explain_type_err(diag, terr, span);
594595
}
@@ -598,17 +599,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
598599
terr: &TypeError<'tcx>)
599600
-> DiagnosticBuilder<'tcx>
600601
{
601-
let span = trace.origin.span();
602-
let failure_str = trace.origin.as_failure_str();
603-
let mut diag = match trace.origin {
604-
TypeOrigin::IfExpressionWithNoElse(_) => {
602+
let span = trace.cause.span;
603+
let failure_str = trace.cause.as_failure_str();
604+
let mut diag = match trace.cause.code {
605+
ObligationCauseCode::IfExpressionWithNoElse => {
605606
struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
606607
},
607608
_ => {
608609
struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
609610
},
610611
};
611-
self.note_type_err(&mut diag, trace.origin, None, Some(trace.values), terr);
612+
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
612613
diag
613614
}
614615

@@ -1695,18 +1696,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
16951696
if let Some((expected, found)) = self.values_str(&trace.values) {
16961697
// FIXME: do we want a "the" here?
16971698
err.span_note(
1698-
trace.origin.span(),
1699+
trace.cause.span,
16991700
&format!("...so that {} (expected {}, found {})",
1700-
trace.origin.as_requirement_str(), expected, found));
1701+
trace.cause.as_requirement_str(), expected, found));
17011702
} else {
17021703
// FIXME: this really should be handled at some earlier stage. Our
17031704
// handling of region checking when type errors are present is
17041705
// *terrible*.
17051706

17061707
err.span_note(
1707-
trace.origin.span(),
1708+
trace.cause.span,
17081709
&format!("...so that {}",
1709-
trace.origin.as_requirement_str()));
1710+
trace.cause.as_requirement_str()));
17101711
}
17111712
}
17121713
infer::Reborrow(span) => {
@@ -1961,3 +1962,45 @@ fn name_to_dummy_lifetime(name: ast::Name) -> hir::Lifetime {
19611962
span: syntax_pos::DUMMY_SP,
19621963
name: name }
19631964
}
1965+
1966+
impl<'tcx> ObligationCause<'tcx> {
1967+
fn as_failure_str(&self) -> &'static str {
1968+
use traits::ObligationCauseCode::*;
1969+
match self.code {
1970+
CompareImplMethodObligation { .. } => "method not compatible with trait",
1971+
MatchExpressionArm { source, .. } => match source {
1972+
hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
1973+
_ => "match arms have incompatible types",
1974+
},
1975+
IfExpression => "if and else have incompatible types",
1976+
IfExpressionWithNoElse => "if may be missing an else clause",
1977+
EquatePredicate => "equality predicate not satisfied",
1978+
MainFunctionType => "main function has wrong type",
1979+
StartFunctionType => "start function has wrong type",
1980+
IntrinsicType => "intrinsic has wrong type",
1981+
MethodReceiver => "mismatched method receiver",
1982+
_ => "mismatched types",
1983+
}
1984+
}
1985+
1986+
fn as_requirement_str(&self) -> &'static str {
1987+
use traits::ObligationCauseCode::*;
1988+
match self.code {
1989+
CompareImplMethodObligation { .. } => "method type is compatible with trait",
1990+
ExprAssignable => "expression is assignable",
1991+
MatchExpressionArm { source, .. } => match source {
1992+
hir::MatchSource::IfLetDesugar{..} => "`if let` arms have compatible types",
1993+
_ => "match arms have compatible types",
1994+
},
1995+
IfExpression => "if and else have compatible types",
1996+
IfExpressionWithNoElse => "if missing an else returns ()",
1997+
EquatePredicate => "equality where clause is satisfied",
1998+
MainFunctionType => "`main` function has the correct type",
1999+
StartFunctionType => "`start` function has the correct type",
2000+
IntrinsicType => "intrinsic has the correct type",
2001+
MethodReceiver => "method receiver has the correct type",
2002+
_ => "types are compatible",
2003+
}
2004+
}
2005+
}
2006+

src/librustc/infer/higher_ranked/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
5858
// Start a snapshot so we can examine "all bindings that were
5959
// created as part of this type comparison".
6060
return self.infcx.commit_if_ok(|snapshot| {
61-
let span = self.trace.origin.span();
61+
let span = self.trace.cause.span;
6262

6363
// First, we instantiate each bound region in the subtype with a fresh
6464
// region variable.
@@ -230,7 +230,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
230230
// created as part of this type comparison".
231231
return self.infcx.commit_if_ok(|snapshot| {
232232
// Instantiate each bound region with a fresh region variable.
233-
let span = self.trace.origin.span();
233+
let span = self.trace.cause.span;
234234
let (a_with_fresh, a_map) =
235235
self.infcx.replace_late_bound_regions_with_fresh_var(
236236
span, HigherRankedType, a);
@@ -247,7 +247,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
247247

248248
// Generalize the regions appearing in result0 if possible
249249
let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
250-
let span = self.trace.origin.span();
250+
let span = self.trace.cause.span;
251251
let result1 =
252252
fold_regions_in(
253253
self.tcx(),
@@ -325,10 +325,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
325325
// Instantiate each bound region with a fresh region variable.
326326
let (a_with_fresh, a_map) =
327327
self.infcx.replace_late_bound_regions_with_fresh_var(
328-
self.trace.origin.span(), HigherRankedType, a);
328+
self.trace.cause.span, HigherRankedType, a);
329329
let (b_with_fresh, b_map) =
330330
self.infcx.replace_late_bound_regions_with_fresh_var(
331-
self.trace.origin.span(), HigherRankedType, b);
331+
self.trace.cause.span, HigherRankedType, b);
332332
let a_vars = var_ids(self, &a_map);
333333
let b_vars = var_ids(self, &b_map);
334334

@@ -341,7 +341,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
341341

342342
// Generalize the regions appearing in result0 if possible
343343
let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
344-
let span = self.trace.origin.span();
344+
let span = self.trace.cause.span;
345345
let result1 =
346346
fold_regions_in(
347347
self.tcx(),
@@ -463,7 +463,7 @@ fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>,
463463
ty::ReVar(r) => { r }
464464
_ => {
465465
span_bug!(
466-
fields.trace.origin.span(),
466+
fields.trace.cause.span,
467467
"found non-region-vid: {:?}",
468468
r);
469469
}

0 commit comments

Comments
 (0)