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.
13 // The job of the coherence phase of typechecking is to ensure that
14 // each trait has at most one implementation for each type. This is
15 // done by the orphan and overlap modules. Then we build up various
16 // mappings. That mapping code resides here.
19 use middle
::lang_items
::UnsizeTraitLangItem
;
20 use middle
::subst
::{self, Subst}
;
22 use middle
::ty
::RegionEscape
;
23 use middle
::ty
::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId}
;
24 use middle
::ty
::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment}
;
25 use middle
::ty
::{Ty, ty_bool, ty_char, ty_enum, ty_err}
;
26 use middle
::ty
::{ty_param, TypeScheme, ty_ptr}
;
27 use middle
::ty
::{ty_rptr, ty_struct, ty_trait, ty_tup}
;
28 use middle
::ty
::{ty_str, ty_vec, ty_float, ty_infer, ty_int}
;
29 use middle
::ty
::{ty_uint, ty_closure, ty_uniq, ty_bare_fn}
;
30 use middle
::ty
::ty_projection
;
32 use middle
::free_region
::FreeRegionMap
;
34 use middle
::infer
::{self, InferCtxt, new_infer_ctxt}
;
35 use std
::cell
::RefCell
;
37 use syntax
::ast
::{Crate, DefId}
;
38 use syntax
::ast
::{Item, ItemImpl}
;
39 use syntax
::ast
::{LOCAL_CRATE, TraitRef}
;
41 use syntax
::ast_map
::NodeItem
;
43 use syntax
::ast_util
::local_def
;
44 use syntax
::codemap
::Span
;
45 use syntax
::parse
::token
;
47 use util
::nodemap
::{DefIdMap, FnvHashMap}
;
48 use util
::ppaux
::Repr
;
54 // Returns the def ID of the base type, if there is one.
55 fn get_base_type_def_id
<'a
, 'tcx
>(inference_context
: &InferCtxt
<'a
, 'tcx
>,
61 ty_struct(def_id
, _
) => {
66 Some(t
.principal_def_id())
70 inference_context
.tcx
.lang_items
.owned_box()
73 ty_bool
| ty_char
| ty_int(..) | ty_uint(..) | ty_float(..) |
74 ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
75 ty_param(..) | ty_err
|
76 ty_ptr(_
) | ty_rptr(_
, _
) | ty_projection(..) => {
80 ty_infer(..) | ty_closure(..) => {
81 // `ty` comes from a user declaration so we should only expect types
82 // that the user can type
83 inference_context
.tcx
.sess
.span_bug(
85 &format
!("coherence encountered unexpected type searching for base type: {}",
86 ty
.repr(inference_context
.tcx
)));
91 struct CoherenceChecker
<'a
, 'tcx
: 'a
> {
92 crate_context
: &'a CrateCtxt
<'a
, 'tcx
>,
93 inference_context
: InferCtxt
<'a
, 'tcx
>,
94 inherent_impls
: RefCell
<DefIdMap
<Rc
<RefCell
<Vec
<ast
::DefId
>>>>>,
97 struct CoherenceCheckVisitor
<'a
, 'tcx
: 'a
> {
98 cc
: &'a CoherenceChecker
<'a
, 'tcx
>
101 impl<'a
, 'tcx
, 'v
> visit
::Visitor
<'v
> for CoherenceCheckVisitor
<'a
, 'tcx
> {
102 fn visit_item(&mut self, item
: &Item
) {
104 //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
106 if let ItemImpl(_
, _
, _
, ref opt_trait
, _
, _
) = item
.node
{
107 self.cc
.check_implementation(item
, opt_trait
.as_ref())
110 visit
::walk_item(self, item
);
114 impl<'a
, 'tcx
> CoherenceChecker
<'a
, 'tcx
> {
115 fn check(&self, krate
: &Crate
) {
116 // Check implementations and traits. This populates the tables
117 // containing the inherent methods and extension methods. It also
118 // builds up the trait inheritance table.
119 let mut visitor
= CoherenceCheckVisitor { cc: self }
;
120 visit
::walk_crate(&mut visitor
, krate
);
122 // Copy over the inherent impls we gathered up during the walk into
124 let mut tcx_inherent_impls
=
125 self.crate_context
.tcx
.inherent_impls
.borrow_mut();
126 for (k
, v
) in &*self.inherent_impls
.borrow() {
127 tcx_inherent_impls
.insert((*k
).clone(),
128 Rc
::new((*v
.borrow()).clone()));
131 // Populate the table of destructors. It might seem a bit strange to
132 // do this here, but it's actually the most convenient place, since
133 // the coherence tables contain the trait -> type mappings.
134 self.populate_destructor_table();
136 // Check to make sure implementations of `Copy` are legal.
137 self.check_implementations_of_copy();
139 // Check to make sure implementations of `CoerceUnsized` are legal
140 // and collect the necessary information from them.
141 self.check_implementations_of_coerce_unsized();
144 fn check_implementation(&self, item
: &Item
, opt_trait
: Option
<&TraitRef
>) {
145 let tcx
= self.crate_context
.tcx
;
146 let impl_did
= local_def(item
.id
);
147 let self_type
= ty
::lookup_item_type(tcx
, impl_did
);
149 // If there are no traits, then this implementation must have a
152 let impl_items
= self.create_impl_from_item(item
);
154 if opt_trait
.is_some() {
155 let trait_ref
= ty
::impl_id_to_trait_ref(self.crate_context
.tcx
, item
.id
);
156 debug
!("(checking implementation) adding impl for trait '{}', item '{}'",
157 trait_ref
.repr(self.crate_context
.tcx
),
158 token
::get_ident(item
.ident
));
160 enforce_trait_manually_implementable(self.crate_context
.tcx
,
163 self.add_trait_impl(trait_ref
, impl_did
);
166 // Add the implementation to the mapping from implementation to base
167 // type def ID, if there is a base type for this implementation and
168 // the implementation does not have any associated traits.
169 match get_base_type_def_id(&self.inference_context
,
175 Some(base_type_def_id
) => {
176 // FIXME: Gather up default methods?
177 if opt_trait
.is_none() {
178 self.add_inherent_impl(base_type_def_id
, impl_did
);
183 tcx
.impl_items
.borrow_mut().insert(impl_did
, impl_items
);
186 // Creates default method IDs and performs type substitutions for an impl
187 // and trait pair. Then, for each provided method in the trait, inserts a
188 // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
189 fn instantiate_default_methods(
192 trait_ref
: &ty
::TraitRef
<'tcx
>,
193 all_impl_items
: &mut Vec
<ImplOrTraitItemId
>) {
194 let tcx
= self.crate_context
.tcx
;
195 debug
!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
196 impl_id
, trait_ref
.repr(tcx
));
198 let impl_type_scheme
= ty
::lookup_item_type(tcx
, impl_id
);
200 let prov
= ty
::provided_trait_methods(tcx
, trait_ref
.def_id
);
201 for trait_method
in &prov
{
203 let new_id
= tcx
.sess
.next_node_id();
204 let new_did
= local_def(new_id
);
206 debug
!("new_did={:?} trait_method={}", new_did
, trait_method
.repr(tcx
));
208 // Create substitutions for the various trait parameters.
210 Rc
::new(subst_receiver_types_in_method_ty(
217 Some(trait_method
.def_id
)));
219 debug
!("new_method_ty={}", new_method_ty
.repr(tcx
));
220 all_impl_items
.push(MethodTraitItemId(new_did
));
222 // construct the polytype for the method based on the
223 // method_ty. it will have all the generics from the
224 // impl, plus its own.
225 let new_polytype
= ty
::TypeScheme
{
226 generics
: new_method_ty
.generics
.clone(),
227 ty
: ty
::mk_bare_fn(tcx
, Some(new_did
),
228 tcx
.mk_bare_fn(new_method_ty
.fty
.clone()))
230 debug
!("new_polytype={}", new_polytype
.repr(tcx
));
232 tcx
.tcache
.borrow_mut().insert(new_did
, new_polytype
);
233 tcx
.predicates
.borrow_mut().insert(new_did
, new_method_ty
.predicates
.clone());
234 tcx
.impl_or_trait_items
236 .insert(new_did
, ty
::MethodTraitItem(new_method_ty
));
238 // Pair the new synthesized ID up with the
240 self.crate_context
.tcx
.provided_method_sources
.borrow_mut()
241 .insert(new_did
, trait_method
.def_id
);
245 fn add_inherent_impl(&self, base_def_id
: DefId
, impl_def_id
: DefId
) {
246 match self.inherent_impls
.borrow().get(&base_def_id
) {
247 Some(implementation_list
) => {
248 implementation_list
.borrow_mut().push(impl_def_id
);
254 self.inherent_impls
.borrow_mut().insert(
256 Rc
::new(RefCell
::new(vec
!(impl_def_id
))));
259 fn add_trait_impl(&self, impl_trait_ref
: ty
::TraitRef
<'tcx
>, impl_def_id
: DefId
) {
260 debug
!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}",
261 impl_trait_ref
, impl_def_id
);
262 let trait_def
= ty
::lookup_trait_def(self.crate_context
.tcx
,
263 impl_trait_ref
.def_id
);
264 trait_def
.record_impl(self.crate_context
.tcx
, impl_def_id
, impl_trait_ref
);
267 // Converts an implementation in the AST to a vector of items.
268 fn create_impl_from_item(&self, item
: &Item
) -> Vec
<ImplOrTraitItemId
> {
270 ItemImpl(_
, _
, _
, ref opt_trait
, _
, ref impl_items
) => {
271 let mut items
: Vec
<ImplOrTraitItemId
> =
272 impl_items
.iter().map(|impl_item
| {
273 match impl_item
.node
{
274 ast
::ConstImplItem(..) => {
275 ConstTraitItemId(local_def(impl_item
.id
))
277 ast
::MethodImplItem(..) => {
278 MethodTraitItemId(local_def(impl_item
.id
))
280 ast
::TypeImplItem(_
) => {
281 TypeTraitItemId(local_def(impl_item
.id
))
283 ast
::MacImplItem(_
) => {
284 self.crate_context
.tcx
.sess
.span_bug(impl_item
.span
,
290 if opt_trait
.is_some() {
291 let trait_ref
= ty
::impl_id_to_trait_ref(self.crate_context
.tcx
,
294 self.instantiate_default_methods(local_def(item
.id
),
302 self.crate_context
.tcx
.sess
.span_bug(item
.span
,
303 "can't convert a non-impl to an impl");
312 fn populate_destructor_table(&self) {
313 let tcx
= self.crate_context
.tcx
;
314 let drop_trait
= match tcx
.lang_items
.drop_trait() {
315 Some(id
) => id
, None
=> { return }
317 ty
::populate_implementations_for_trait_if_necessary(tcx
, drop_trait
);
318 let drop_trait
= ty
::lookup_trait_def(tcx
, drop_trait
);
320 let impl_items
= tcx
.impl_items
.borrow();
322 drop_trait
.for_each_impl(tcx
, |impl_did
| {
323 let items
= impl_items
.get(&impl_did
).unwrap();
324 if items
.is_empty() {
325 // We'll error out later. For now, just don't ICE.
328 let method_def_id
= items
[0];
330 let self_type
= ty
::lookup_item_type(tcx
, impl_did
);
331 match self_type
.ty
.sty
{
332 ty
::ty_enum(type_def_id
, _
) |
333 ty
::ty_struct(type_def_id
, _
) |
334 ty
::ty_closure(type_def_id
, _
) => {
335 tcx
.destructor_for_type
337 .insert(type_def_id
, method_def_id
.def_id());
340 .insert(method_def_id
.def_id());
343 // Destructors only work on nominal types.
344 if impl_did
.krate
== ast
::LOCAL_CRATE
{
346 match tcx
.map
.find(impl_did
.node
) {
347 Some(ast_map
::NodeItem(item
)) => {
348 span_err
!(tcx
.sess
, item
.span
, E0120
,
349 "the Drop trait may only be implemented on structures");
352 tcx
.sess
.bug("didn't find impl in ast \
358 tcx
.sess
.bug("found external impl of Drop trait on \
359 something other than a struct");
366 /// Ensures that implementations of the built-in trait `Copy` are legal.
367 fn check_implementations_of_copy(&self) {
368 let tcx
= self.crate_context
.tcx
;
369 let copy_trait
= match tcx
.lang_items
.copy_trait() {
373 ty
::populate_implementations_for_trait_if_necessary(tcx
, copy_trait
);
374 let copy_trait
= ty
::lookup_trait_def(tcx
, copy_trait
);
376 copy_trait
.for_each_impl(tcx
, |impl_did
| {
377 debug
!("check_implementations_of_copy: impl_did={}",
380 if impl_did
.krate
!= ast
::LOCAL_CRATE
{
381 debug
!("check_implementations_of_copy(): impl not in this \
386 let self_type
= ty
::lookup_item_type(tcx
, impl_did
);
387 debug
!("check_implementations_of_copy: self_type={} (bound)",
388 self_type
.repr(tcx
));
390 let span
= tcx
.map
.span(impl_did
.node
);
391 let param_env
= ParameterEnvironment
::for_item(tcx
, impl_did
.node
);
392 let self_type
= self_type
.ty
.subst(tcx
, ¶m_env
.free_substs
);
393 assert
!(!self_type
.has_escaping_regions());
395 debug
!("check_implementations_of_copy: self_type={} (free)",
396 self_type
.repr(tcx
));
398 match ty
::can_type_implement_copy(¶m_env
, span
, self_type
) {
400 Err(ty
::FieldDoesNotImplementCopy(name
)) => {
401 span_err
!(tcx
.sess
, span
, E0204
,
402 "the trait `Copy` may not be \
403 implemented for this type; field \
404 `{}` does not implement `Copy`",
405 token
::get_name(name
))
407 Err(ty
::VariantDoesNotImplementCopy(name
)) => {
408 span_err
!(tcx
.sess
, span
, E0205
,
409 "the trait `Copy` may not be \
410 implemented for this type; variant \
411 `{}` does not implement `Copy`",
412 token
::get_name(name
))
414 Err(ty
::TypeIsStructural
) => {
415 span_err
!(tcx
.sess
, span
, E0206
,
416 "the trait `Copy` may not be implemented \
417 for this type; type is not a structure or \
420 Err(ty
::TypeHasDestructor
) => {
421 span_err
!(tcx
.sess
, span
, E0184
,
422 "the trait `Copy` may not be implemented for this type; \
423 the type has a destructor");
429 /// Process implementations of the built-in trait `CoerceUnsized`.
430 fn check_implementations_of_coerce_unsized(&self) {
431 let tcx
= self.crate_context
.tcx
;
432 let coerce_unsized_trait
= match tcx
.lang_items
.coerce_unsized_trait() {
436 let unsize_trait
= match tcx
.lang_items
.require(UnsizeTraitLangItem
) {
439 tcx
.sess
.fatal(&format
!("`CoerceUnsized` implementation {}", err
));
443 let trait_def
= ty
::lookup_trait_def(tcx
, coerce_unsized_trait
);
445 trait_def
.for_each_impl(tcx
, |impl_did
| {
446 debug
!("check_implementations_of_coerce_unsized: impl_did={}",
449 if impl_did
.krate
!= ast
::LOCAL_CRATE
{
450 debug
!("check_implementations_of_coerce_unsized(): impl not \
455 let source
= ty
::lookup_item_type(tcx
, impl_did
).ty
;
456 let trait_ref
= ty
::impl_id_to_trait_ref(self.crate_context
.tcx
,
458 let target
= *trait_ref
.substs
.types
.get(subst
::TypeSpace
, 0);
459 debug
!("check_implementations_of_coerce_unsized: {} -> {} (bound)",
460 source
.repr(tcx
), target
.repr(tcx
));
462 let span
= tcx
.map
.span(impl_did
.node
);
463 let param_env
= ParameterEnvironment
::for_item(tcx
, impl_did
.node
);
464 let source
= source
.subst(tcx
, ¶m_env
.free_substs
);
465 let target
= target
.subst(tcx
, ¶m_env
.free_substs
);
466 assert
!(!source
.has_escaping_regions());
468 debug
!("check_implementations_of_coerce_unsized: {} -> {} (free)",
469 source
.repr(tcx
), target
.repr(tcx
));
471 let infcx
= new_infer_ctxt(tcx
);
473 let check_mutbl
= |mt_a
: ty
::mt
<'tcx
>, mt_b
: ty
::mt
<'tcx
>,
474 mk_ptr
: &Fn(Ty
<'tcx
>) -> Ty
<'tcx
>| {
475 if (mt_a
.mutbl
, mt_b
.mutbl
) == (ast
::MutImmutable
, ast
::MutMutable
) {
476 infcx
.report_mismatched_types(span
, mk_ptr(mt_b
.ty
),
477 target
, &ty
::terr_mutability
);
479 (mt_a
.ty
, mt_b
.ty
, unsize_trait
, None
)
481 let (source
, target
, trait_def_id
, kind
) = match (&source
.sty
, &target
.sty
) {
482 (&ty
::ty_uniq(a
), &ty
::ty_uniq(b
)) => (a
, b
, unsize_trait
, None
),
484 (&ty
::ty_rptr(r_a
, mt_a
), &ty
::ty_rptr(r_b
, mt_b
)) => {
485 infer
::mk_subr(&infcx
, infer
::RelateObjectBound(span
), *r_b
, *r_a
);
486 check_mutbl(mt_a
, mt_b
, &|ty
| ty
::mk_imm_rptr(tcx
, r_b
, ty
))
489 (&ty
::ty_rptr(_
, mt_a
), &ty
::ty_ptr(mt_b
)) |
490 (&ty
::ty_ptr(mt_a
), &ty
::ty_ptr(mt_b
)) => {
491 check_mutbl(mt_a
, mt_b
, &|ty
| ty
::mk_imm_ptr(tcx
, ty
))
494 (&ty
::ty_struct(def_id_a
, substs_a
), &ty
::ty_struct(def_id_b
, substs_b
)) => {
495 if def_id_a
!= def_id_b
{
496 let source_path
= ty
::item_path_str(tcx
, def_id_a
);
497 let target_path
= ty
::item_path_str(tcx
, def_id_b
);
498 span_err
!(tcx
.sess
, span
, E0377
,
499 "the trait `CoerceUnsized` may only be implemented \
500 for a coercion between structures with the same \
501 definition; expected {}, found {}",
502 source_path
, target_path
);
506 let origin
= infer
::Misc(span
);
507 let fields
= ty
::lookup_struct_fields(tcx
, def_id_a
);
508 let diff_fields
= fields
.iter().enumerate().filter_map(|(i
, f
)| {
509 let ty
= ty
::lookup_field_type_unsubstituted(tcx
, def_id_a
, f
.id
);
510 let (a
, b
) = (ty
.subst(tcx
, substs_a
), ty
.subst(tcx
, substs_b
));
511 if infcx
.sub_types(false, origin
, b
, a
).is_ok() {
516 }).collect
::<Vec
<_
>>();
518 if diff_fields
.is_empty() {
519 span_err
!(tcx
.sess
, span
, E0374
,
520 "the trait `CoerceUnsized` may only be implemented \
521 for a coercion between structures with one field \
522 being coerced, none found");
524 } else if diff_fields
.len() > 1 {
525 span_err
!(tcx
.sess
, span
, E0375
,
526 "the trait `CoerceUnsized` may only be implemented \
527 for a coercion between structures with one field \
528 being coerced, but {} fields need coercions: {}",
529 diff_fields
.len(), diff_fields
.iter().map(|&(i
, a
, b
)| {
530 let name
= fields
[i
].name
;
531 format
!("{} ({} to {})",
532 if name
== token
::special_names
::unnamed_field
{
535 token
::get_name(name
).to_string()
539 }).collect
::<Vec
<_
>>().connect(", "));
543 let (i
, a
, b
) = diff_fields
[0];
544 let kind
= ty
::CustomCoerceUnsized
::Struct(i
);
545 (a
, b
, coerce_unsized_trait
, Some(kind
))
549 span_err
!(tcx
.sess
, span
, E0376
,
550 "the trait `CoerceUnsized` may only be implemented \
551 for a coercion between structures");
556 let mut fulfill_cx
= traits
::FulfillmentContext
::new();
558 // Register an obligation for `A: Trait<B>`.
559 let cause
= traits
::ObligationCause
::misc(span
, impl_did
.node
);
560 let predicate
= traits
::predicate_for_trait_def(tcx
, cause
, trait_def_id
,
561 0, source
, vec
![target
]);
562 fulfill_cx
.register_predicate_obligation(&infcx
, predicate
);
564 // Check that all transitive obligations are satisfied.
565 if let Err(errors
) = fulfill_cx
.select_all_or_error(&infcx
, ¶m_env
) {
566 traits
::report_fulfillment_errors(&infcx
, &errors
);
569 // Finally, resolve all regions.
570 let mut free_regions
= FreeRegionMap
::new();
571 free_regions
.relate_free_regions_from_predicates(tcx
, ¶m_env
.caller_bounds
);
572 infcx
.resolve_regions_and_report_errors(&free_regions
, impl_did
.node
);
574 if let Some(kind
) = kind
{
575 tcx
.custom_coerce_unsized_kinds
.borrow_mut().insert(impl_did
, kind
);
581 fn enforce_trait_manually_implementable(tcx
: &ty
::ctxt
, sp
: Span
, trait_def_id
: ast
::DefId
) {
582 if tcx
.sess
.features
.borrow().unboxed_closures
{
583 // the feature gate allows all of them
586 let did
= Some(trait_def_id
);
587 let li
= &tcx
.lang_items
;
589 let trait_name
= if did
== li
.fn_trait() {
591 } else if did
== li
.fn_mut_trait() {
593 } else if did
== li
.fn_once_trait() {
596 return // everything OK
598 span_err
!(tcx
.sess
, sp
, E0183
, "manual implementations of `{}` are experimental", trait_name
);
599 fileline_help
!(tcx
.sess
, sp
,
600 "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
603 fn subst_receiver_types_in_method_ty
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>,
605 impl_type_scheme
: &ty
::TypeScheme
<'tcx
>,
606 trait_ref
: &ty
::TraitRef
<'tcx
>,
607 new_def_id
: ast
::DefId
,
608 method
: &ty
::Method
<'tcx
>,
609 provided_source
: Option
<ast
::DefId
>)
612 let combined_substs
= ty
::make_substs_for_receiver_types(tcx
, trait_ref
, method
);
614 debug
!("subst_receiver_types_in_method_ty: combined_substs={}",
615 combined_substs
.repr(tcx
));
617 let method_predicates
= method
.predicates
.subst(tcx
, &combined_substs
);
618 let mut method_generics
= method
.generics
.subst(tcx
, &combined_substs
);
620 // replace the type parameters declared on the trait with those
622 for &space
in &[subst
::TypeSpace
, subst
::SelfSpace
] {
623 method_generics
.types
.replace(
625 impl_type_scheme
.generics
.types
.get_slice(space
).to_vec());
626 method_generics
.regions
.replace(
628 impl_type_scheme
.generics
.regions
.get_slice(space
).to_vec());
631 debug
!("subst_receiver_types_in_method_ty: method_generics={}",
632 method_generics
.repr(tcx
));
634 let method_fty
= method
.fty
.subst(tcx
, &combined_substs
);
636 debug
!("subst_receiver_types_in_method_ty: method_ty={}",
637 method
.fty
.repr(tcx
));
644 method
.explicit_self
,
647 ImplContainer(impl_id
),
652 pub fn check_coherence(crate_context
: &CrateCtxt
) {
654 crate_context
: crate_context
,
655 inference_context
: new_infer_ctxt(crate_context
.tcx
),
656 inherent_impls
: RefCell
::new(FnvHashMap()),
657 }.check(crate_context
.tcx
.map
.krate());
658 unsafety
::check(crate_context
.tcx
);
659 orphan
::check(crate_context
.tcx
);
660 overlap
::check(crate_context
.tcx
);