Skip to content

Commit b23c76e

Browse files
borsarielb1
authored andcommitted
Backported merge of rust-lang#45890 - arielb1:self-first, r=eddyb
check::method - unify receivers before normalizing method signatures Normalizing method signatures can unify inference variables, which can cause receiver unification to fail. Unify the receivers first to avoid that. Fixes rust-lang#36701. Fixes rust-lang#45801. Fixes rust-lang#45855. r? @eddyb beta-nominating because rust-lang#43880 made this ICE happen in more cases (the code in that issue ICEs post-rust-lang#43880 only, but the unit test here ICEs on all versions).
1 parent a8d6ab7 commit b23c76e

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

src/librustc_typeck/check/method/confirm.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use hir::def_id::DefId;
1616
use rustc::ty::subst::Substs;
1717
use rustc::traits;
1818
use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty};
19+
use rustc::ty::subst::Subst;
1920
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, OverloadedDeref};
2021
use rustc::ty::fold::TypeFoldable;
2122
use rustc::infer::{self, InferOk};
@@ -84,9 +85,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
8485
// Adjust the self expression the user provided and obtain the adjusted type.
8586
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
8687

87-
// Make sure nobody calls `drop()` explicitly.
88-
self.enforce_illegal_method_limitations(&pick);
89-
9088
// Create substitutions for the method's type parameters.
9189
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
9290
let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);
@@ -96,6 +94,22 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
9694
// Create the final signature for the method, replacing late-bound regions.
9795
let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs);
9896

97+
// Unify the (adjusted) self type with what the method expects.
98+
//
99+
// SUBTLE: if we want good error messages, because of "guessing" while matching
100+
// traits, no trait system method can be called before this point because they
101+
// could alter our Self-type, except for normalizing the receiver from the
102+
// signature (which is also done during probing).
103+
let method_sig_rcvr =
104+
self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
105+
self.unify_receivers(self_ty, method_sig_rcvr);
106+
107+
let (method_sig, method_predicates) =
108+
self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
109+
110+
// Make sure nobody calls `drop()` explicitly.
111+
self.enforce_illegal_method_limitations(&pick);
112+
99113
// If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
100114
// something which derefs to `Self` actually implements the trait and the caller
101115
// wanted to make a static dispatch on it but forgot to import the trait.
@@ -106,9 +120,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
106120
// appropriate hint suggesting to import the trait.
107121
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(&method_predicates);
108122

109-
// Unify the (adjusted) self type with what the method expects.
110-
self.unify_receivers(self_ty, method_sig.inputs()[0]);
111-
112123
// Add any trait/regions obligations specified on the method's type parameters.
113124
// We won't add these if we encountered an illegal sized bound, so that we can use
114125
// a custom error in that case.
@@ -338,6 +349,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
338349
///////////////////////////////////////////////////////////////////////////
339350
//
340351

352+
// NOTE: this returns the *unnormalized* predicates and method sig. Because of
353+
// inference guessing, the predicates and method signature can't be normalized
354+
// until we unify the `Self` type.
341355
fn instantiate_method_sig(&mut self,
342356
pick: &probe::Pick<'tcx>,
343357
all_substs: &'tcx Substs<'tcx>)
@@ -352,8 +366,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
352366
let def_id = pick.item.def_id;
353367
let method_predicates = self.tcx.predicates_of(def_id)
354368
.instantiate(self.tcx, all_substs);
355-
let method_predicates = self.normalize_associated_types_in(self.span,
356-
&method_predicates);
357369

358370
debug!("method_predicates after subst = {:?}", method_predicates);
359371

@@ -369,7 +381,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
369381
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
370382
method_sig);
371383

372-
let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
384+
let method_sig = method_sig.subst(self.tcx, all_substs);
373385
debug!("type scheme substituted, method_sig={:?}", method_sig);
374386

375387
(method_sig, method_predicates)

src/test/compile-fail/issue-45801.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2017 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+
struct Params;
12+
13+
pub trait Plugin<E: ?Sized> {
14+
type Error;
15+
}
16+
17+
pub trait Pluggable {
18+
fn get_ref<P: Plugin<Self>>(&mut self) -> Option<P::Error> {
19+
None
20+
}
21+
}
22+
23+
struct Foo;
24+
impl Plugin<Foo> for Params {
25+
type Error = ();
26+
}
27+
28+
impl<T: Copy> Pluggable for T {}
29+
30+
fn handle(req: &mut i32) {
31+
req.get_ref::<Params>();
32+
//~^ ERROR the trait bound `Params: Plugin<i32>` is not satisfied
33+
}
34+
35+
fn main() {}

0 commit comments

Comments
 (0)