diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index a152e06eb06aa..97fa9631fb7e2 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -122,7 +122,7 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t // If this trait has builtin-kind supertraits, meet them. let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id); debug!("checking impl with self type {:?}", ty::get(self_ty).sty); - check_builtin_bounds(cx, self_ty, trait_def.bounds, |missing| { + check_builtin_bounds(cx.tcx, self_ty, trait_def.bounds, |missing| { cx.tcx.sess.span_err(self_type.span, format!("the type `{}', which does not fulfill `{}`, cannot implement this \ trait", ty_to_str(cx.tcx, self_ty), missing.user_string(cx.tcx))); @@ -357,14 +357,14 @@ fn check_ty(cx: &mut Context, aty: &Ty) { } // Calls "any_missing" if any bounds were missing. -pub fn check_builtin_bounds(cx: &Context, +pub fn check_builtin_bounds(tcx: &ty::ctxt, ty: ty::t, bounds: ty::BuiltinBounds, any_missing: |ty::BuiltinBounds|) { - let kind = ty::type_contents(cx.tcx, ty); + let kind = ty::type_contents(tcx, ty); let mut missing = ty::EmptyBuiltinBounds(); for bound in bounds.iter() { - if !kind.meets_bound(cx.tcx, bound) { + if !kind.meets_bound(tcx, bound) { missing.add(bound); } } @@ -377,7 +377,7 @@ pub fn check_typaram_bounds(cx: &Context, sp: Span, ty: ty::t, type_param_def: &ty::TypeParameterDef) { - check_builtin_bounds(cx, + check_builtin_bounds(cx.tcx, ty, type_param_def.bounds.builtin_bounds, |missing| { @@ -393,7 +393,7 @@ pub fn check_typaram_bounds(cx: &Context, pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t, bounds: ty::BuiltinBounds, referenced_ty: Option) { - check_builtin_bounds(cx, ty, bounds, |missing| { + check_builtin_bounds(cx.tcx, ty, bounds, |missing| { // Will be Some if the freevar is implicitly borrowed (stack closure). // Emit a less mysterious error message in this case. match referenced_ty { @@ -415,7 +415,7 @@ pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t, pub fn check_trait_cast_bounds(cx: &Context, sp: Span, ty: ty::t, bounds: ty::BuiltinBounds) { - check_builtin_bounds(cx, ty, bounds, |missing| { + check_builtin_bounds(cx.tcx, ty, bounds, |missing| { cx.tcx.sess.span_err(sp, format!("cannot pack type `{}`, which does not fulfill \ `{}`, as a trait bounded by {}", diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 3f50a64e63096..52f847bac6130 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -9,6 +9,7 @@ // except according to those terms. +use middle::kind::check_builtin_bounds; use middle::ty; use middle::ty::{AutoAddEnv, AutoDerefRef, AutoObject, param_ty}; use middle::ty_fold::TypeFolder; @@ -26,6 +27,7 @@ use middle::subst::Subst; use util::common::indenter; use util::ppaux; use util::ppaux::Repr; +use util::ppaux::UserString; use collections::HashSet; use std::cell::RefCell; @@ -124,6 +126,27 @@ fn lookup_vtables_for_param(vcx: &VtableContext, is_early: bool) -> vtable_param_res { let tcx = vcx.tcx(); + // FIXME(#13231): this will likely break once opt-in builtin kinds are implemented + if !type_param_bounds.builtin_bounds.is_empty() { + match fixup_ty(vcx, span, ty, is_early) { + Some(fix_ty) => { + check_builtin_bounds( + vcx.tcx(), + fix_ty, + type_param_bounds.builtin_bounds, + |missing: ty::BuiltinBounds| { + vcx.tcx().sess.span_err( + span, + format!("instantiating a type parameter with an incompatible type \ + `{}`, which does not fulfill `{}`", + vcx.infcx.ty_to_str(ty), + missing.user_string(tcx))); + }); + } + None => {} + } + } + // ty is the value supplied for the type parameter A... let mut param_result = Vec::new(); diff --git a/src/test/compile-fail/issue-10751.rs b/src/test/compile-fail/issue-10751.rs new file mode 100644 index 0000000000000..801e6a1d6bfe4 --- /dev/null +++ b/src/test/compile-fail/issue-10751.rs @@ -0,0 +1,47 @@ +// Copyright 2014 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 builtin bounds are checked when searching for an +// implementation of a trait +use std::cell::Cell; + +trait A {} +trait B {} +trait C {} +trait D {} +impl A for T {} +impl B for T {} +impl C for T {} +impl D for T {} + +fn main() { + let a = 3; + let b = &a; + let c = &b as &A; //~ ERROR instantiating a type parameter with an incompatible type `&int` + let d: &A = &b; //~ ERROR instantiating a type parameter with an incompatible type `&int` + let e = &b as &B; //~ ERROR instantiating a type parameter with an incompatible type `&int` + let f: &B = &b; //~ ERROR instantiating a type parameter with an incompatible type `&int` + let g = &~b as &C; //~ ERROR instantiating a type parameter with an incompatible type `~&int` + let h: &C = &~b; //~ ERROR instantiating a type parameter with an incompatible type `~&int` + let i = &Cell::new(b) as &D; + //~^ ERROR instantiating a type parameter with an incompatible type `std::cell::Cell<&int>` + let j: &D = &Cell::new(b); + //~^ ERROR instantiating a type parameter with an incompatible type `std::cell::Cell<&int>` + + // These are all ok: int is 'static + Send + Copy + Share + let k: &A = b; + let l: &B = b; + let m: &C = b; + let n: &D = b; + let o = b as &A; + let p = b as &B; + let q = b as &C; + let r = b as &D; +}