Skip to content

Commit

Permalink
start writing some typeck docs (incomplete)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Sep 19, 2017
1 parent 032fdef commit 38813cf
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 44 deletions.
48 changes: 48 additions & 0 deletions src/librustc_typeck/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
NB: This crate is part of the Rust compiler. For an overview of the
compiler as a whole, see
[the README.md file found in `librustc`](../librustc/README.md).

The `rustc_typeck` crate contains the source for "type collection" and
"type checking", as well as a few other bits of related functionality.
(It draws heavily on the [type inferencing][infer] and
[trait solving][traits] code found in librustc.)

[infer]: ../librustc/infer/README.md
[traits]: ../librustc/traits/README.md

## Type collection

Type "collection" is the process of convering the types found in the
HIR (`hir::Ty`), which represent the syntactic things that the user
wrote, into the **internal representation** used by the compiler
(`Ty<'tcx>`) -- we also do similar conversions for where-clauses and
other bits of the function signature.

To try and get a sense for the difference, consider this function:

```rust
struct Foo { }
fn foo(x: Foo, y: self::Foo) { .. }
// ^^^ ^^^^^^^^^
```

Those two parameters `x` and `y` each have the same type: but they
will have distinct `hir::Ty` nodes. Those nodes will have different
spans, and of course they encode the path somewhat differently. But
once they are "collected" into `Ty<'tcx>` nodes, they will be
represented by the exact same internal type.

Collection is defined as a bundle of queries (e.g., `type_of`) for
computing information about the various functions, traits, and other
items in the crate being compiled. Note that each of these queries is
concerned with *interprocedural* things -- for example, for a function
definition, collection will figure out the type and signature of the
function, but it will not visit the *body* of the function in any way,
nor examine type annotations on local variables (that's the job of
type *checking*).

For more details, see the `collect` module.

## Type checking

TODO
59 changes: 15 additions & 44 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,21 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*
# Collect phase
The collect phase of type check has the job of visiting all items,
determining their type, and writing that type into the `tcx.types`
table. Despite its name, this table does not really operate as a
*cache*, at least not for the types of items defined within the
current crate: we assume that after the collect phase, the types of
all local items will be present in the table.
Unlike most of the types that are present in Rust, the types computed
for each item are in fact type schemes. This means that they are
generic types that may have type parameters. TypeSchemes are
represented by a pair of `Generics` and `Ty`. Type
parameters themselves are represented as `ty_param()` instances.
The phasing of type conversion is somewhat complicated. There is no
clear set of phases we can enforce (e.g., converting traits first,
then types, or something like that) because the user can introduce
arbitrary interdependencies. So instead we generally convert things
lazilly and on demand, and include logic that checks for cycles.
Demand is driven by calls to `AstConv::get_item_type_scheme` or
`AstConv::trait_def`.
Currently, we "convert" types and traits in two phases (note that
conversion only affects the types of items / enum variants / methods;
it does not e.g. compute the types of individual expressions):
0. Intrinsics
1. Trait/Type definitions
Conversion itself is done by simply walking each of the items in turn
and invoking an appropriate function (e.g., `trait_def_of_item` or
`convert_item`). However, it is possible that while converting an
item, we may need to compute the *type scheme* or *trait definition*
for other items.
There are some shortcomings in this design:
- Because the item generics include defaults, cycles through type
parameter defaults are illegal even if those defaults are never
employed. This is not necessarily a bug.
*/
//! "Collection" is the process of determining the type and other external
//! details of each item in Rust. Collection is specifically concerned
//! with *interprocedural* things -- for example, for a function
//! definition, collection will figure out the type and signature of the
//! function, but it will not visit the *body* of the function in any way,
//! nor examine type annotations on local variables (that's the job of
//! type *checking*).
//!
//! Collecting is ultimately defined by a bundle of queries that
//! inquire after various facts about the items in the crate (e.g.,
//! `type_of`, `generics_of`, `predicates_of`, etc). See the `provide` function
//! for the full set.
//!
//! At present, however, we do run collection across all items in the
//! crate as a kind of pass. This should eventually be factored away.

use astconv::{AstConv, Bounds};
use lint;
Expand Down

0 comments on commit 38813cf

Please sign in to comment.