Skip to content

Latest commit

 

History

History
43 lines (34 loc) · 5.15 KB

param_env_acquisition.md

File metadata and controls

43 lines (34 loc) · 5.15 KB

Which ParamEnv do I use?

When needing a ParamEnv in the compiler there are a few options for obtaining one:

  • The correct env is already in scope simply use it (or pass it down the call stack to where you are).
  • The tcx.param_env(def_id) query
  • Use ParamEnv::new to construct an env with an arbitrary set of where clauses. Then call traits::normalize_param_env_or_error which will handle normalizing and elaborating all the where clauses in the env for you.
  • Creating an empty environment via ParamEnv::reveal_all or ParamEnv::empty

In the large majority of cases a ParamEnv when required already exists somewhere in scope or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing ParamEnv:

Using the param_env query to obtain an env is generally done at the start of some kind of analysis and then passed everywhere that a ParamEnv is required. For example the type checker will create a ParamEnv for the item it is type checking and then pass it around everywhere.

Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (i.e. [compare_method_predicate_entailment][method_pred_entailment] as mentioned earlier).

Creating an empty environment via ParamEnv::empty is almost always wrong. There are very few places where we actually know that the environment should be empty. One of the only places where we do actually know this is after monomorphization, however the ParamEnv there should be constructed via ParamEnv::reveal_all instead as at this point we should be able to determine the hidden type of opaque types. Codegen/Post-mono is one of the only places that should be using ParamEnv::reveal_all.

An additional piece of complexity here is specifying the Reveal (see linked docs for explanation of what reveal does) used for the ParamEnv. When constructing a param env using the param_env query it will have Reveal::UserFacing, if Reveal::All is desired then the tcx.param_env_reveal_all_normalized query can be used instead.

The ParamEnv type has a method ParamEnv::with_reveal_all_normalized which converts an existing ParamEnv into one with Reveal::All specified. Where possible the previously mentioned query should be preferred as it is more efficient.