Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8a09bc6

Browse files
committedApr 27, 2018
Auto merge of #48995 - aravind-pg:canonical-query, r=nikomatsakis
Create a canonical trait query for `evaluate_obligation` This builds on the canonical query machinery introduced in #48411 to introduce a new canonical trait query for `evaluate_obligation` in the trait selector. Also ports most callers of the original `evaluate_obligation` to the new system (except in coherence, which requires support for intercrate mode). Closes #48537. r? @nikomatsakis
2 parents e05b78d + e423dcc commit 8a09bc6

File tree

21 files changed

+341
-109
lines changed

21 files changed

+341
-109
lines changed
 

‎src/librustc/dep_graph/dep_node.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
7070
use std::fmt;
7171
use std::hash::Hash;
7272
use syntax_pos::symbol::InternedString;
73-
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
73+
use traits::query::{CanonicalProjectionGoal,
74+
CanonicalTyGoal, CanonicalPredicateGoal};
7475
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
7576
use ty::subst::Substs;
7677

@@ -643,6 +644,7 @@ define_dep_nodes!( <'tcx>
643644
[] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
644645
[] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
645646
[] DropckOutlives(CanonicalTyGoal<'tcx>),
647+
[] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
646648

647649
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
648650

‎src/librustc/traits/coherence.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
154154
recursion_depth: 0,
155155
predicate: p })
156156
.chain(obligations)
157-
.find(|o| !selcx.evaluate_obligation(o));
157+
.find(|o| !selcx.predicate_may_hold_fatal(o));
158+
// FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
159+
// to the canonical trait query form, `infcx.predicate_may_hold`, once
160+
// the new system supports intercrate mode (which coherence needs).
158161

159162
if let Some(failing_obligation) = opt_failing_obligation {
160163
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);

‎src/librustc/traits/error_reporting.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use super::{
2424
SelectionContext,
2525
SelectionError,
2626
ObjectSafetyViolation,
27+
Overflow,
2728
};
2829

2930
use errors::DiagnosticBuilder;
@@ -659,8 +660,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
659660
predicate: ty::Predicate::Trait(predicate),
660661
.. obligation.clone()
661662
};
662-
let mut selcx = SelectionContext::new(self);
663-
if selcx.evaluate_obligation(&unit_obligation) {
663+
if self.predicate_may_hold(&unit_obligation) {
664664
err.note("the trait is implemented for `()`. \
665665
Possibly this error has been caused by changes to \
666666
Rust's type-inference algorithm \
@@ -830,6 +830,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
830830
}
831831
err.struct_error(self.tcx, span, "constant expression")
832832
}
833+
834+
Overflow => {
835+
bug!("overflow should be handled before the `report_selection_error` path");
836+
}
833837
};
834838
self.note_obligation_cause(&mut err, obligation);
835839
err.emit();
@@ -872,7 +876,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
872876
.count();
873877

874878
let mut trait_type = trait_ref.self_ty();
875-
let mut selcx = SelectionContext::new(self);
876879

877880
for refs_remaining in 0..refs_number {
878881
if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) =
@@ -886,7 +889,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
886889
obligation.param_env,
887890
new_trait_ref.to_predicate());
888891

889-
if selcx.evaluate_obligation(&new_obligation) {
892+
if self.predicate_may_hold(&new_obligation) {
890893
let sp = self.tcx.sess.codemap()
891894
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
892895

@@ -1322,7 +1325,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13221325
cleaned_pred.to_predicate()
13231326
);
13241327

1325-
selcx.evaluate_obligation(&obligation)
1328+
self.predicate_may_hold(&obligation)
13261329
})
13271330
}
13281331

‎src/librustc/traits/fulfill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
333333
if data.is_global() {
334334
// no type variables present, can use evaluation for better caching.
335335
// FIXME: consider caching errors too.
336-
if selcx.evaluate_obligation_conservatively(&obligation) {
336+
if selcx.infcx().predicate_must_hold(&obligation) {
337337
debug!("selecting trait `{:?}` at depth {} evaluated to holds",
338338
data, obligation.recursion_depth);
339339
return Ok(Some(vec![]))

‎src/librustc/traits/mod.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub use self::object_safety::ObjectSafetyViolation;
4141
pub use self::object_safety::MethodViolationCode;
4242
pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
4343
pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
44-
pub use self::select::IntercrateAmbiguityCause;
44+
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
4545
pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
4646
pub use self::specialize::{SpecializesCache, find_associated_item};
4747
pub use self::engine::TraitEngine;
@@ -74,6 +74,19 @@ pub enum IntercrateMode {
7474
Fixed
7575
}
7676

77+
// The mode that trait queries run in
78+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
79+
pub enum TraitQueryMode {
80+
// Standard/un-canonicalized queries get accurate
81+
// spans etc. passed in and hence can do reasonable
82+
// error reporting on their own.
83+
Standard,
84+
// Canonicalized queries get dummy spans and hence
85+
// must generally propagate errors to
86+
// pre-canonicalization callsites.
87+
Canonical,
88+
}
89+
7790
/// An `Obligation` represents some trait reference (e.g. `int:Eq`) for
7891
/// which the vtable must be found. The process of finding a vtable is
7992
/// called "resolving" the `Obligation`. This process consists of
@@ -349,6 +362,7 @@ pub enum SelectionError<'tcx> {
349362
ty::error::TypeError<'tcx>),
350363
TraitNotObjectSafe(DefId),
351364
ConstEvalFailure(ConstEvalErr<'tcx>),
365+
Overflow,
352366
}
353367

354368
pub struct FulfillmentError<'tcx> {
@@ -550,8 +564,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
550564
predicate: trait_ref.to_predicate(),
551565
};
552566

553-
let result = SelectionContext::new(infcx)
554-
.evaluate_obligation_conservatively(&obligation);
567+
let result = infcx.predicate_must_hold(&obligation);
555568
debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
556569
ty, infcx.tcx.item_path_str(def_id), result);
557570

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use infer::InferCtxt;
12+
use infer::canonical::{Canonical, Canonicalize};
13+
use traits::{EvaluationResult, PredicateObligation, SelectionContext,
14+
TraitQueryMode, OverflowError};
15+
use traits::query::CanonicalPredicateGoal;
16+
use ty::{ParamEnvAnd, Predicate, TyCtxt};
17+
18+
impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
19+
/// Evaluates whether the predicate can be satisfied (by any means)
20+
/// in the given `ParamEnv`.
21+
pub fn predicate_may_hold(
22+
&self,
23+
obligation: &PredicateObligation<'tcx>,
24+
) -> bool {
25+
self.evaluate_obligation(obligation).may_apply()
26+
}
27+
28+
/// Evaluates whether the predicate can be satisfied in the given
29+
/// `ParamEnv`, and returns `false` if not certain. However, this is
30+
/// not entirely accurate if inference variables are involved.
31+
pub fn predicate_must_hold(
32+
&self,
33+
obligation: &PredicateObligation<'tcx>,
34+
) -> bool {
35+
self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk
36+
}
37+
38+
// Helper function that canonicalizes and runs the query, as well as handles
39+
// overflow.
40+
fn evaluate_obligation(
41+
&self,
42+
obligation: &PredicateObligation<'tcx>,
43+
) -> EvaluationResult {
44+
let (c_pred, _) =
45+
self.canonicalize_query(&obligation.param_env.and(obligation.predicate));
46+
// Run canonical query. If overflow occurs, rerun from scratch but this time
47+
// in standard trait query mode so that overflow is handled appropriately
48+
// within `SelectionContext`.
49+
match self.tcx.global_tcx().evaluate_obligation(c_pred) {
50+
Ok(result) => result,
51+
Err(OverflowError) => {
52+
let mut selcx =
53+
SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
54+
selcx.evaluate_obligation_recursively(obligation)
55+
.expect("Overflow should be caught earlier in standard query mode")
56+
}
57+
}
58+
}
59+
}
60+
61+
impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for ParamEnvAnd<'tcx, Predicate<'tcx>> {
62+
type Canonicalized = CanonicalPredicateGoal<'gcx>;
63+
64+
fn intern(
65+
_gcx: TyCtxt<'_, 'gcx, 'gcx>,
66+
value: Canonical<'gcx, Self::Lifted>,
67+
) -> Self::Canonicalized {
68+
value
69+
}
70+
}

‎src/librustc/traits/query/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use infer::canonical::Canonical;
1919
use ty::{self, Ty};
2020

2121
pub mod dropck_outlives;
22+
pub mod evaluate_obligation;
2223
pub mod normalize;
2324
pub mod normalize_erasing_regions;
2425

@@ -27,6 +28,9 @@ pub type CanonicalProjectionGoal<'tcx> =
2728

2829
pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
2930

31+
pub type CanonicalPredicateGoal<'tcx> =
32+
Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
33+
3034
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
3135
pub struct NoSolution;
3236

‎src/librustc/traits/select.rs

Lines changed: 158 additions & 85 deletions
Large diffs are not rendered by default.

‎src/librustc/traits/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
177177
super::ConstEvalFailure(ref err) => {
178178
tcx.lift(err).map(super::ConstEvalFailure)
179179
}
180+
super::Overflow => bug!() // FIXME: ape ConstEvalFailure?
180181
}
181182
}
182183
}

‎src/librustc/ty/maps/config.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use dep_graph::SerializedDepNodeIndex;
1212
use hir::def_id::{CrateNum, DefId, DefIndex};
1313
use mir::interpret::{GlobalId};
14-
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
14+
use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
1515
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
1616
use ty::subst::Substs;
1717
use ty::maps::queries;
@@ -73,6 +73,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_region
7373
}
7474
}
7575

76+
impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
77+
fn describe(_tcx: TyCtxt, goal: CanonicalPredicateGoal<'tcx>) -> String {
78+
format!("evaluating trait selection obligation `{}`", goal.value.value)
79+
}
80+
}
81+
7682
impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
7783
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
7884
format!("computing whether `{}` is `Copy`", env.value)

‎src/librustc/ty/maps/keys.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! Defines the set of legal keys that can be used in queries.
1212
1313
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
14-
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
14+
use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
1515
use ty::{self, Ty, TyCtxt};
1616
use ty::subst::Substs;
1717
use ty::fast_reject::SimplifiedType;
@@ -200,3 +200,13 @@ impl<'tcx> Key for CanonicalTyGoal<'tcx> {
200200
DUMMY_SP
201201
}
202202
}
203+
204+
impl<'tcx> Key for CanonicalPredicateGoal<'tcx> {
205+
fn map_crate(&self) -> CrateNum {
206+
LOCAL_CRATE
207+
}
208+
209+
fn default_span(&self, _tcx: TyCtxt) -> Span {
210+
DUMMY_SP
211+
}
212+
}

‎src/librustc/ty/maps/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ use mir;
3232
use mir::interpret::{GlobalId};
3333
use session::{CompileResult, CrateDisambiguator};
3434
use session::config::OutputFilenames;
35-
use traits::Vtable;
36-
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution};
35+
use traits::{self, Vtable};
36+
use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
37+
CanonicalTyGoal, NoSolution};
3738
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
3839
use traits::query::normalize::NormalizationResult;
3940
use traits::specialization_graph;
@@ -433,6 +434,12 @@ define_maps! { <'tcx>
433434
NoSolution,
434435
>,
435436

437+
/// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
438+
/// `infcx.predicate_must_hold()` instead.
439+
[] fn evaluate_obligation: EvaluateObligation(
440+
CanonicalPredicateGoal<'tcx>
441+
) -> Result<traits::EvaluationResult, traits::OverflowError>,
442+
436443
[] fn substitute_normalize_and_test_predicates:
437444
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
438445

‎src/librustc/ty/maps/plumbing.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
977977
DepKind::NormalizeProjectionTy |
978978
DepKind::NormalizeTyAfterErasingRegions |
979979
DepKind::DropckOutlives |
980+
DepKind::EvaluateObligation |
980981
DepKind::SubstituteNormalizeAndTestPredicates |
981982
DepKind::InstanceDefSizeEstimate |
982983
DepKind::ProgramClausesForEnv |
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::traits::{EvaluationResult, Obligation, ObligationCause,
12+
OverflowError, SelectionContext, TraitQueryMode};
13+
use rustc::traits::query::CanonicalPredicateGoal;
14+
use rustc::ty::{ParamEnvAnd, TyCtxt};
15+
use syntax::codemap::DUMMY_SP;
16+
17+
crate fn evaluate_obligation<'tcx>(
18+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
19+
goal: CanonicalPredicateGoal<'tcx>,
20+
) -> Result<EvaluationResult, OverflowError> {
21+
tcx.infer_ctxt().enter(|ref infcx| {
22+
let (
23+
ParamEnvAnd {
24+
param_env,
25+
value: predicate,
26+
},
27+
_canonical_inference_vars,
28+
) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
29+
30+
let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
31+
let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
32+
33+
selcx.evaluate_obligation_recursively(&obligation)
34+
})
35+
}

‎src/librustc_traits/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern crate syntax;
2222
extern crate syntax_pos;
2323

2424
mod dropck_outlives;
25+
mod evaluate_obligation;
2526
mod normalize_projection_ty;
2627
mod normalize_erasing_regions;
2728
mod util;
@@ -38,6 +39,7 @@ pub fn provide(p: &mut Providers) {
3839
normalize_erasing_regions::normalize_ty_after_erasing_regions,
3940
program_clauses_for: lowering::program_clauses_for,
4041
program_clauses_for_env: lowering::program_clauses_for_env,
42+
evaluate_obligation: evaluate_obligation::evaluate_obligation,
4143
..*p
4244
};
4345
}

‎src/librustc_typeck/check/autoderef.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,15 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
120120

121121
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
122122

123-
let mut selcx = traits::SelectionContext::new(self.fcx);
124123
let obligation = traits::Obligation::new(cause.clone(),
125124
self.fcx.param_env,
126125
trait_ref.to_predicate());
127-
if !selcx.evaluate_obligation(&obligation) {
126+
if !self.fcx.predicate_may_hold(&obligation) {
128127
debug!("overloaded_deref_ty: cannot match obligation");
129128
return None;
130129
}
131130

131+
let mut selcx = traits::SelectionContext::new(self.fcx);
132132
let normalized = traits::normalize_projection_type(&mut selcx,
133133
self.fcx.param_env,
134134
ty::ProjectionTy::from_ref_and_name(

‎src/librustc_typeck/check/method/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
277277
poly_trait_ref.to_predicate());
278278

279279
// Now we want to know if this can be matched
280-
let mut selcx = traits::SelectionContext::new(self);
281-
if !selcx.evaluate_obligation(&obligation) {
280+
if !self.predicate_may_hold(&obligation) {
282281
debug!("--> Cannot match obligation");
283282
return None; // Cannot be matched, no such method resolution is possible.
284283
}

‎src/librustc_typeck/check/method/probe.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
11731173
let predicate = trait_ref.to_predicate();
11741174
let obligation =
11751175
traits::Obligation::new(cause.clone(), self.param_env, predicate);
1176-
if !selcx.evaluate_obligation(&obligation) {
1176+
if !self.predicate_may_hold(&obligation) {
11771177
if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
11781178
// This candidate's primary obligation doesn't even
11791179
// select - don't bother registering anything in
@@ -1201,7 +1201,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
12011201
// Evaluate those obligations to see if they might possibly hold.
12021202
for o in candidate_obligations.into_iter().chain(sub_obligations) {
12031203
let o = self.resolve_type_vars_if_possible(&o);
1204-
if !selcx.evaluate_obligation(&o) {
1204+
if !self.predicate_may_hold(&o) {
12051205
result = ProbeResult::NoMatch;
12061206
if let &ty::Predicate::Trait(ref pred) = &o.predicate {
12071207
possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);

‎src/librustc_typeck/check/method/suggest.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use hir::def::Def;
1919
use hir::def_id::{CRATE_DEF_INDEX, DefId};
2020
use middle::lang_items::FnOnceTraitLangItem;
2121
use namespace::Namespace;
22-
use rustc::traits::{Obligation, SelectionContext};
22+
use rustc::traits::Obligation;
2323
use util::nodemap::FxHashSet;
2424

2525
use syntax::ast;
@@ -65,7 +65,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
6565
self.body_id,
6666
self.param_env,
6767
poly_trait_ref.to_predicate());
68-
SelectionContext::new(self).evaluate_obligation(&obligation)
68+
self.predicate_may_hold(&obligation)
6969
})
7070
})
7171
}

‎src/test/compile-fail/issue-23080-2.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// ignore-tidy-linelength
1212

13+
//~^^^^^^^^^^^^ ERROR
14+
1315
#![feature(optin_builtin_traits)]
1416

1517
unsafe auto trait Trait {
@@ -22,5 +24,4 @@ fn call_method<T: Trait>(x: T) {}
2224
fn main() {
2325
// ICE
2426
call_method(());
25-
//~^ ERROR
2627
}

‎src/test/ui/impl-trait/auto-trait-leak.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ error[E0391]: cycle detected when processing `cycle1`
3434
LL | fn cycle1() -> impl Clone {
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^^
3636
|
37+
note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
3738
note: ...which requires processing `cycle2::{{impl-Trait}}`...
3839
--> $DIR/auto-trait-leak.rs:49:16
3940
|
@@ -44,6 +45,7 @@ note: ...which requires processing `cycle2`...
4445
|
4546
LL | fn cycle2() -> impl Clone {
4647
| ^^^^^^^^^^^^^^^^^^^^^^^^^
48+
note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
4749
note: ...which requires processing `cycle1::{{impl-Trait}}`...
4850
--> $DIR/auto-trait-leak.rs:42:16
4951
|

0 commit comments

Comments
 (0)
Please sign in to comment.