about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2022-06-08 19:21:01 +0200
committerGitHub <noreply@github.com>2022-06-08 14:21:01 -0300
commitc0cc3b934d174efc19d6876c219461848a16289b (patch)
tree81b2616f479381fb81d4451d68f6aa2a418535a1 /src/doc/rustc-dev-guide
parenta335dd2d31d1082529df0fde38f07efd291ced1a (diff)
downloadrust-c0cc3b934d174efc19d6876c219461848a16289b.tar.gz
rust-c0cc3b934d174efc19d6876c219461848a16289b.zip
add section on user types (#1359)
* add section on user types

* line length

* review

* Update src/borrow_check/type_check.md

Co-authored-by: Yuki Okushi <jtitor@2k36.org>
Diffstat (limited to 'src/doc/rustc-dev-guide')
-rw-r--r--src/doc/rustc-dev-guide/src/borrow_check/type_check.md54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/doc/rustc-dev-guide/src/borrow_check/type_check.md b/src/doc/rustc-dev-guide/src/borrow_check/type_check.md
index 1485f2ae87c..69456d870ea 100644
--- a/src/doc/rustc-dev-guide/src/borrow_check/type_check.md
+++ b/src/doc/rustc-dev-guide/src/borrow_check/type_check.md
@@ -8,3 +8,57 @@ this type-check, we also uncover the region constraints that apply to
 the program.
 
 TODO -- elaborate further? Maybe? :)
+
+## User types
+
+At the start of MIR type-check, we replace all regions in the body with new unconstrained regions.
+However, this would cause us to accept the following program:
+```rust
+fn foo<'a>(x: &'a u32) {
+    let y: &'static u32 = x;
+}
+```
+By erasing the lifetimes in the type of `y` we no longer know that it is supposed to be `'static`,
+ignoring the intentions of the user.
+
+To deal with this we remember all places where the user explicitly mentioned a type during
+HIR type-check as [`CanonicalUserTypeAnnotations`][annot].
+
+There are two different annotations we care about:
+- explicit type ascriptions, e.g. `let y: &'static u32` results in `UserType::Ty(&'static u32)`.
+- explicit generic arguments, e.g. `x.foo<&'a u32, Vec<String>>`
+results in `UserType::TypeOf(foo_def_id, [&'a u32, Vec<String>])`.
+
+As we do not want the region inference from the HIR type-check to influence MIR typeck,
+we store the user type right after lowering it from the HIR.
+This means that it may still contain inference variables,
+which is why we are using **canonical** user type annotations.
+We replace all inference variables with existential bound variables instead.
+Something like `let x: Vec<_>` would therefore result in `exists<T> UserType::Ty(Vec<T>)`.
+
+A pattern like `let Foo(x): Foo<&'a u32>` has a user type `Foo<&'a u32>` but
+the actual type of `x` should only be `&'a u32`. For this, we use a [`UserTypeProjection`][proj].
+
+In the MIR, we deal with user types in two slightly different ways.
+
+Given a MIR local corresponding to a variable in a pattern which has an explicit type annotation,
+we require the type of that local to be equal to the type of the [`UserTypeProjection`][proj].
+This is directly stored in the [`LocalDecl`][decl].
+
+We also constrain the type of scrutinee expressions, e.g. the type of `x` in `let _: &'a u32 = x;`.
+Here `T_x` only has to be a subtype of the user type, so we instead use
+[`StatementKind::AscribeUserType`][stmt] for that.
+
+Note that we do not directly use the user type as the MIR typechecker
+doesn't really deal with type and const inference variables. We instead store the final
+[`inferred_type`][inf] from the HIR type-checker. During MIR typeck, we then replace its regions
+with new nll inference vars and relate it with the actual `UserType` to get the correct region
+constraints again.
+
+After the MIR type-check, all user type annotations get discarded, as they aren't needed anymore.
+
+[annot]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html
+[proj]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.UserTypeProjection.html
+[decl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.LocalDecl.html
+[stmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.AscribeUserType
+[inf]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html#structfield.inferred_ty
\ No newline at end of file