about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbobtwinkles <srkoser+github@gmail.com>2018-02-21 21:38:10 -0500
committerbobtwinkles <srkoser+github@gmail.com>2018-03-05 02:47:08 -0500
commit264c2013eb25f929135a5f4fc8b20b3baeae2af1 (patch)
treee22bca351b0585a4a6a462c2ed9c0085f689afcc
parente2746d870017c869b84fc56ecd63f5e4f9646c96 (diff)
downloadrust-264c2013eb25f929135a5f4fc8b20b3baeae2af1.tar.gz
rust-264c2013eb25f929135a5f4fc8b20b3baeae2af1.zip
Fix #48276
The ExplicitSelf::determine function expects to be able to compare regions.
However, when the compare_self_type error reporting code runs we haven't
resolved bound regions yet. Thus we replace them with free regions first.
-rw-r--r--src/librustc_typeck/check/compare_method.rs4
-rw-r--r--src/test/ui/issue-48276.rs43
-rw-r--r--src/test/ui/issue-48276.stderr27
3 files changed, 74 insertions, 0 deletions
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index d0419382bc3..a3a1f2a9307 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -504,6 +504,10 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let param_env = ty::ParamEnv::empty(Reveal::All);
 
         tcx.infer_ctxt().enter(|infcx| {
+            let self_arg_ty = tcx.liberate_late_bound_regions(
+                method.def_id,
+                &ty::Binder(self_arg_ty)
+            );
             let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
             match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
                 ExplicitSelf::ByValue => "self".to_string(),
diff --git a/src/test/ui/issue-48276.rs b/src/test/ui/issue-48276.rs
new file mode 100644
index 00000000000..30d11a2e37f
--- /dev/null
+++ b/src/test/ui/issue-48276.rs
@@ -0,0 +1,43 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #48276 - ICE when self type does not match what is
+// required by a trait and regions are involved.
+
+trait MyFrom<A> {
+    fn from(a: A) -> Self;
+}
+
+struct A;
+
+impl<'a, 'b> MyFrom<A> for &'a str {
+    fn from(self: &'a Self) -> &'b str {
+        //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait
+        "asdf"
+    }
+}
+
+struct B;
+
+impl From<A> for B {
+    fn from(&self) -> B {
+        //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait
+        B
+    }
+}
+
+impl From<A> for &'static str {
+    fn from(&self) -> &'static str {
+        //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait
+        ""
+    }
+}
+
+fn main(){}
diff --git a/src/test/ui/issue-48276.stderr b/src/test/ui/issue-48276.stderr
new file mode 100644
index 00000000000..43986c5f4d8
--- /dev/null
+++ b/src/test/ui/issue-48276.stderr
@@ -0,0 +1,27 @@
+error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/issue-48276.rs:21:5
+   |
+15 |     fn from(a: A) -> Self;
+   |     ---------------------- trait method declared without `&self`
+...
+21 |     fn from(self: &'a Self) -> &'b str {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+
+error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/issue-48276.rs:30:5
+   |
+30 |     fn from(&self) -> B {
+   |     ^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+   |
+   = note: `from` from trait: `fn(T) -> Self`
+
+error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/issue-48276.rs:37:5
+   |
+37 |     fn from(&self) -> &'static str {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+   |
+   = note: `from` from trait: `fn(T) -> Self`
+
+error: aborting due to 3 previous errors
+