From 115a443cee40ef51f7ea1f79668bab1149b2d898 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 8 Jan 2015 10:45:56 -0500 Subject: [PATCH] Normalize types in supertraits when checking that impls are valid during wf. Fixes #20559. --- src/librustc/middle/traits/project.rs | 3 +- src/librustc_typeck/check/wf.rs | 9 +++- ...sociated-types-projection-in-supertrait.rs | 50 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/associated-types-projection-in-supertrait.rs diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 1a7e712f180d..377ed7f3a783 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -244,12 +244,11 @@ pub struct Normalized<'tcx,T> { pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>; impl<'tcx,T> Normalized<'tcx,T> { - fn with(self, value: U) -> Normalized<'tcx,U> { + pub fn with(self, value: U) -> Normalized<'tcx,U> { Normalized { value: value, obligations: self.obligations } } } - pub fn normalize_projection_type<'a,'b,'tcx>( selcx: &'a mut SelectionContext<'b,'tcx>, projection_ty: ty::ProjectionTy<'tcx>, diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index b17ecdaf59c6..89de1ea80fcf 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -235,9 +235,16 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // Find the supertrait bounds. This will add `int:Bar`. let poly_trait_ref = ty::Binder(trait_ref); let predicates = ty::predicates_for_trait_ref(fcx.tcx(), &poly_trait_ref); - for predicate in predicates.into_iter() { + let predicates = { + let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx); + traits::normalize(selcx, cause.clone(), &predicates) + }; + for predicate in predicates.value.into_iter() { fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate)); } + for obligation in predicates.obligations.into_iter() { + fcx.register_predicate(obligation); + } }); } } diff --git a/src/test/run-pass/associated-types-projection-in-supertrait.rs b/src/test/run-pass/associated-types-projection-in-supertrait.rs new file mode 100644 index 000000000000..e6fec675b036 --- /dev/null +++ b/src/test/run-pass/associated-types-projection-in-supertrait.rs @@ -0,0 +1,50 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are handle to correctly handle a projection type +// that appears in a supertrait bound. Issue #20559. + +trait A +{ + type TA; +} + +trait B +{ + fn foo (&self, t : TB) -> String; +} + +trait C : B<::TA> { } + +struct X; + +impl A for X +{ + type TA = i32; +} + +struct Y; + +impl C for Y { } + +// Both of these impls are required for successful compilation +impl B for Y +{ + fn foo (&self, t : i32) -> String + { + format!("First {}", t) + } +} + +fn main () +{ + let y = Y; + assert_eq!(y.foo(5), format!("First 5")); +}