1 // Copyright 2014 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.
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.
11 use middle::subst::{SelfSpace, FnSpace};
13 use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
14 use middle::traits::{Obligation, obligation_for_builtin_bound};
15 use middle::traits::{FulfillmentError, CodeSelectionError, CodeAmbiguity};
16 use middle::traits::{ObligationCause};
17 use middle::ty::{mod, Ty};
18 use middle::typeck::check::{FnCtxt,
19 structurally_resolved_type};
20 use middle::typeck::infer;
23 use syntax::codemap::Span;
24 use util::common::ErrorReported;
25 use util::ppaux::{UserString, Repr, ty_to_string};
27 pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
28 cast_expr: &ast::Expr,
29 source_expr: &ast::Expr,
30 target_object_ty: Ty<'tcx>)
32 debug!("check_object_cast(cast_expr={}, target_object_ty={})",
33 cast_expr.repr(fcx.tcx()),
34 target_object_ty.repr(fcx.tcx()));
36 // Look up vtables for the type we're casting to,
37 // passing in the source and target type. The source
38 // must be a pointer type suitable to the object sigil,
39 // e.g.: `&x as &Trait` or `box x as Box<Trait>`
40 let source_ty = fcx.expr_ty(source_expr);
41 let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
42 debug!("source_ty={}", source_ty.repr(fcx.tcx()));
43 match (&source_ty.sty, &target_object_ty.sty) {
44 (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
45 let object_trait = object_trait(&object_trait_ty);
47 // Ensure that if ~T is cast to ~Trait, then T : Trait
48 push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
49 check_object_safety(fcx.tcx(), object_trait, source_expr.span);
52 (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
53 mutbl: referent_mutbl }),
54 &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
55 mutbl: target_mutbl })) =>
57 let object_trait = object_trait(&object_trait_ty);
58 if !mutability_allowed(referent_mutbl, target_mutbl) {
59 fcx.tcx().sess.span_err(source_expr.span,
60 "types differ in mutability");
62 // Ensure that if &'a T is cast to &'b Trait, then T : Trait
63 push_cast_obligation(fcx, cast_expr,
67 // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
68 infer::mk_subr(fcx.infcx(),
69 infer::RelateObjectBound(source_expr.span),
73 check_object_safety(fcx.tcx(), object_trait, source_expr.span);
77 (_, &ty::ty_uniq(..)) => {
78 fcx.ccx.tcx.sess.span_err(
80 format!("can only cast an boxed pointer \
81 to a boxed object, not a {}",
82 ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
85 (_, &ty::ty_rptr(..)) => {
86 fcx.ccx.tcx.sess.span_err(
88 format!("can only cast a &-pointer \
89 to an &-object, not a {}",
90 ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
94 fcx.tcx().sess.span_bug(
96 "expected object type");
100 fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
102 ty::ty_trait(ref ty_trait) => &**ty_trait,
103 _ => panic!("expected ty_trait")
107 fn mutability_allowed(a_mutbl: ast::Mutability,
108 b_mutbl: ast::Mutability)
110 a_mutbl == b_mutbl ||
111 (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
114 fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
115 cast_expr: &ast::Expr,
116 object_trait: &ty::TyTrait<'tcx>,
117 referent_ty: Ty<'tcx>) {
118 let object_trait_ref =
119 register_object_cast_obligations(fcx,
124 // Finally record the object_trait_ref for use during trans
125 // (it would prob be better not to do this, but it's just kind
126 // of a pain to have to reconstruct it).
127 fcx.write_object_cast(cast_expr.id, object_trait_ref);
131 // Check that a trait is 'object-safe'. This should be checked whenever a trait object
132 // is created (by casting or coercion, etc.). A trait is object-safe if all its
133 // methods are object-safe. A trait method is object-safe if it does not take
134 // self by value, has no type parameters and does not use the `Self` type, except
136 pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
137 object_trait: &ty::TyTrait<'tcx>,
139 // Skip the fn_once lang item trait since only the compiler should call
140 // `call_once` which is the method which takes self by value. What could go
142 match tcx.lang_items.fn_once_trait() {
143 Some(def_id) if def_id == object_trait.principal.def_id => return,
147 let trait_items = ty::trait_items(tcx, object_trait.principal.def_id);
149 let mut errors = Vec::new();
150 for item in trait_items.iter() {
152 ty::MethodTraitItem(ref m) => {
153 errors.push(check_object_safety_of_method(tcx, &**m))
155 ty::TypeTraitItem(_) => {}
159 let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
160 if errors.peek().is_some() {
161 let trait_name = ty::item_path_str(tcx, object_trait.principal.def_id);
162 span_err!(tcx.sess, span, E0038,
163 "cannot convert to a trait object because trait `{}` is not object-safe",
167 tcx.sess.note(msg.as_slice());
171 /// Returns a vec of error messages. If hte vec is empty - no errors!
173 /// There are some limitations to calling functions through an object, because (a) the self
174 /// type is not known (that's the whole point of a trait instance, after all, to obscure the
175 /// self type) and (b) the call must go through a vtable and hence cannot be monomorphized.
176 fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>,
177 method: &ty::Method<'tcx>)
179 let mut msgs = Vec::new();
181 let method_name = method.name.repr(tcx);
183 match method.explicit_self {
184 ty::ByValueExplicitSelfCategory => { // reason (a) above
185 msgs.push(format!("cannot call a method (`{}`) with a by-value \
186 receiver through a trait object", method_name))
189 ty::StaticExplicitSelfCategory => {
190 // Static methods are always object-safe since they
191 // can't be called through a trait object
194 ty::ByReferenceExplicitSelfCategory(..) |
195 ty::ByBoxExplicitSelfCategory => {}
199 let check_for_self_ty = |ty| {
200 if ty::type_has_self(ty) {
202 "cannot call a method (`{}`) whose type contains \
203 a self-type (`{}`) through a trait object",
204 method_name, ty_to_string(tcx, ty)))
209 let ref sig = method.fty.sig;
210 for &input_ty in sig.inputs[1..].iter() {
211 match check_for_self_ty(input_ty) {
212 Some(msg) => msgs.push(msg),
216 if let ty::FnConverging(result_type) = sig.output {
217 match check_for_self_ty(result_type) {
218 Some(msg) => msgs.push(msg),
223 if method.generics.has_type_params(FnSpace) {
225 msgs.push(format!("cannot call a generic method (`{}`) through a trait object",
233 pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
235 object_trait: &ty::TyTrait<'tcx>,
236 referent_ty: Ty<'tcx>)
237 -> Rc<ty::TraitRef<'tcx>>
239 // We can only make objects from sized types.
240 let sized_obligation =
241 traits::obligation_for_builtin_bound(
243 traits::ObligationCause::new(span, traits::ObjectSized),
246 match sized_obligation {
247 Ok(sized_obligation) => {
248 fcx.register_obligation(sized_obligation);
250 Err(ErrorReported) => { }
253 // This is just for better error reporting. Kinda goofy. The object type stuff
254 // needs some refactoring so there is a more convenient type to pass around.
255 let object_trait_ty =
256 ty::mk_trait(fcx.tcx(),
257 object_trait.principal.clone(),
258 object_trait.bounds);
260 debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
261 referent_ty.repr(fcx.tcx()),
262 object_trait_ty.repr(fcx.tcx()));
264 // Take the type parameters from the object type, but set
265 // the Self type (which is unknown, for the object type)
266 // to be the type we are casting from.
267 let mut object_substs = object_trait.principal.substs.clone();
268 assert!(object_substs.self_ty().is_none());
269 object_substs.types.push(SelfSpace, referent_ty);
271 // Create the obligation for casting from T to Trait.
272 let object_trait_ref =
273 Rc::new(ty::TraitRef { def_id: object_trait.principal.def_id,
274 substs: object_substs });
275 let object_obligation =
277 ObligationCause::new(span,
278 traits::ObjectCastObligation(object_trait_ty)),
279 object_trait_ref.clone());
280 fcx.register_obligation(object_obligation);
282 // Create additional obligations for all the various builtin
283 // bounds attached to the object cast. (In other words, if the
284 // object type is Foo+Send, this would create an obligation
285 // for the Send check.)
286 for builtin_bound in object_trait.bounds.builtin_bounds.iter() {
287 let obligation = obligation_for_builtin_bound(
289 ObligationCause::new(span,
290 traits::ObjectCastObligation(object_trait_ty)),
294 Ok(obligation) => fcx.register_obligation(obligation),
302 pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
303 debug!("select_all_fcx_obligations_or_error");
305 let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
306 let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
311 Err(errors) => { report_fulfillment_errors(fcx, &errors); }
315 fn resolve_trait_ref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, obligation: &Obligation<'tcx>)
316 -> (Rc<ty::TraitRef<'tcx>>, Ty<'tcx>)
319 fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
320 &*obligation.trait_ref);
322 trait_ref.substs.self_ty().unwrap();
323 (Rc::new(trait_ref), self_ty)
326 pub fn report_fulfillment_errors<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
327 errors: &Vec<FulfillmentError<'tcx>>) {
328 for error in errors.iter() {
329 report_fulfillment_error(fcx, error);
333 pub fn report_fulfillment_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
334 error: &FulfillmentError<'tcx>) {
336 CodeSelectionError(ref e) => {
337 report_selection_error(fcx, &error.obligation, e);
340 maybe_report_ambiguity(fcx, &error.obligation);
345 pub fn report_selection_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
346 obligation: &Obligation<'tcx>,
347 error: &SelectionError<'tcx>)
351 let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
352 fcx.tcx().sess.span_err(
353 obligation.cause.span,
355 "overflow evaluating the trait `{}` for the type `{}`",
356 trait_ref.user_string(fcx.tcx()),
357 self_ty.user_string(fcx.tcx())).as_slice());
358 note_obligation_cause(fcx, obligation);
361 let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
362 if !ty::type_is_error(self_ty) {
363 fcx.tcx().sess.span_err(
364 obligation.cause.span,
366 "the trait `{}` is not implemented for the type `{}`",
367 trait_ref.user_string(fcx.tcx()),
368 self_ty.user_string(fcx.tcx())).as_slice());
369 note_obligation_cause(fcx, obligation);
372 OutputTypeParameterMismatch(ref expected_trait_ref, ref e) => {
373 let expected_trait_ref =
374 fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
375 &**expected_trait_ref);
376 let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
377 if !ty::type_is_error(self_ty) {
378 fcx.tcx().sess.span_err(
379 obligation.cause.span,
381 "type mismatch: the type `{}` implements the trait `{}`, \
382 but the trait `{}` is required ({})",
383 self_ty.user_string(fcx.tcx()),
384 expected_trait_ref.user_string(fcx.tcx()),
385 trait_ref.user_string(fcx.tcx()),
386 ty::type_err_to_str(fcx.tcx(), e)).as_slice());
387 note_obligation_cause(fcx, obligation);
393 pub fn maybe_report_ambiguity<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
394 obligation: &Obligation<'tcx>) {
395 // Unable to successfully determine, probably means
396 // insufficient type information, but could mean
397 // ambiguous impls. The latter *ought* to be a
398 // coherence violation, so we don't report it here.
399 let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
400 debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
401 trait_ref.repr(fcx.tcx()),
402 self_ty.repr(fcx.tcx()),
403 obligation.repr(fcx.tcx()));
404 let all_types = &trait_ref.substs.types;
405 if all_types.iter().any(|&t| ty::type_is_error(t)) {
406 } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
407 // This is kind of a hack: it frequently happens that some earlier
408 // error prevents types from being fully inferred, and then we get
409 // a bunch of uninteresting errors saying something like "<generic
410 // #0> doesn't implement Sized". It may even be true that we
411 // could just skip over all checks where the self-ty is an
412 // inference variable, but I was afraid that there might be an
413 // inference variable created, registered as an obligation, and
414 // then never forced by writeback, and hence by skipping here we'd
415 // be ignoring the fact that we don't KNOW the type works
416 // out. Though even that would probably be harmless, given that
417 // we're only talking about builtin traits, which are known to be
418 // inhabited. But in any case I just threw in this check for
419 // has_errors() to be sure that compilation isn't happening
420 // anyway. In that case, why inundate the user.
421 if !fcx.tcx().sess.has_errors() {
422 if fcx.ccx.tcx.lang_items.sized_trait()
423 .map_or(false, |sized_id| sized_id == trait_ref.def_id) {
424 fcx.tcx().sess.span_err(
425 obligation.cause.span,
427 "unable to infer enough type information about `{}`; type annotations \
429 self_ty.user_string(fcx.tcx())).as_slice());
431 fcx.tcx().sess.span_err(
432 obligation.cause.span,
434 "unable to infer enough type information to \
435 locate the impl of the trait `{}` for \
436 the type `{}`; type annotations required",
437 trait_ref.user_string(fcx.tcx()),
438 self_ty.user_string(fcx.tcx())).as_slice());
439 note_obligation_cause(fcx, obligation);
442 } else if !fcx.tcx().sess.has_errors() {
443 // Ambiguity. Coherence should have reported an error.
444 fcx.tcx().sess.span_bug(
445 obligation.cause.span,
447 "coherence failed to report ambiguity: \
448 cannot locate the impl of the trait `{}` for \
450 trait_ref.user_string(fcx.tcx()),
451 self_ty.user_string(fcx.tcx())).as_slice());
455 /// Select as many obligations as we can at present.
456 pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) {
459 fcx.inh.fulfillment_cx
461 .select_where_possible(fcx.infcx(), &fcx.inh.param_env, fcx)
464 Err(errors) => { report_fulfillment_errors(fcx, &errors); }
468 /// Try to select any fcx obligation that we haven't tried yet, in an effort to improve inference.
469 /// You could just call `select_fcx_obligations_where_possible` except that it leads to repeated
471 pub fn select_new_fcx_obligations(fcx: &FnCtxt) {
473 fcx.inh.fulfillment_cx
475 .select_new_obligations(fcx.infcx(), &fcx.inh.param_env, fcx)
478 Err(errors) => { report_fulfillment_errors(fcx, &errors); }
482 fn note_obligation_cause<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
483 obligation: &Obligation<'tcx>) {
485 let trait_name = ty::item_path_str(tcx, obligation.trait_ref.def_id);
486 match obligation.cause.code {
487 traits::MiscObligation => { }
488 traits::ItemObligation(item_def_id) => {
489 let item_name = ty::item_path_str(tcx, item_def_id);
491 obligation.cause.span,
493 "the trait `{}` must be implemented because it is required by `{}`",
495 item_name).as_slice());
497 traits::ObjectCastObligation(object_ty) => {
499 obligation.cause.span,
501 "the trait `{}` must be implemented for the cast \
502 to the object type `{}`",
504 fcx.infcx().ty_to_string(object_ty)).as_slice());
506 traits::RepeatVec => {
508 obligation.cause.span,
509 "the `Copy` trait is required because the \
510 repeated element will be copied");
512 traits::VariableType(_) => {
514 obligation.cause.span,
515 "all local variables must have a statically known size");
517 traits::ReturnType => {
519 obligation.cause.span,
520 "the return type of a function must have a \
521 statically known size");
523 traits::AssignmentLhsSized => {
525 obligation.cause.span,
526 "the left-hand-side of an assignment must have a statically known size");
528 traits::StructInitializerSized => {
530 obligation.cause.span,
531 "structs must have a statically known size to be initialized");
533 traits::DropTrait => {
534 span_note!(tcx.sess, obligation.cause.span,
535 "cannot implement a destructor on a \
536 structure or enumeration that does not satisfy Send");
537 span_help!(tcx.sess, obligation.cause.span,
538 "use \"#[unsafe_destructor]\" on the implementation \
539 to force the compiler to allow this");
541 traits::ClosureCapture(var_id, closure_span) => {
542 let name = ty::local_var_name_str(tcx, var_id);
543 span_note!(tcx.sess, closure_span,
544 "the closure that captures `{}` requires that all captured variables \"
545 implement the trait `{}`",
549 traits::FieldSized => {
550 span_note!(tcx.sess, obligation.cause.span,
551 "only the last field of a struct or enum variant \
552 may have a dynamically sized type")
554 traits::ObjectSized => {
555 span_note!(tcx.sess, obligation.cause.span,
556 "only sized types can be made into objects");